LCOV - code coverage report
Current view: top level - gdk - gdk_join.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1989 2999 66.3 %
Date: 2024-12-19 23:10:26 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      658311 : joinparamcheck(BAT *l, BAT *r1, BAT *r2, BAT *sl, BAT *sr, const char *func)
      87             : {
      88     1663669 :         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      658311 :         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       85711 : 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       85711 :         BAT *r1 = NULL, *r2 = NULL, *r3 = NULL;
     116       85711 :         BUN maxsize, size;
     117             : 
     118             :         /* if nil_on_miss is set, we really need a right output */
     119       85711 :         assert(!nil_on_miss || r2p != NULL || r3p != NULL);
     120             : 
     121       85711 :         lkey |= lcnt <= 1;
     122       85711 :         rkey |= rcnt <= 1;
     123             : 
     124       85711 :         *r1p = NULL;
     125       85711 :         if (r2p)
     126       32201 :                 *r2p = NULL;
     127       85711 :         if (r3p)
     128         344 :                 *r3p = NULL;
     129       85711 :         if (lcnt == 0) {
     130             :                 /* there is nothing to match */
     131             :                 maxsize = 0;
     132       70826 :         } 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       70900 :         } 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       46766 :         } else if (lkey) {
     142             :                 /* each entry on right is matched at most once */
     143       11403 :                 if (nil_on_miss) {
     144             :                         /* one entry left could match all right, and
     145             :                          * all other entries left match nil */
     146          15 :                         maxsize = lcnt + rcnt - 1;
     147             :                 } else {
     148             :                         maxsize = rcnt;
     149             :                 }
     150       35363 :         } 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       35365 :         } else if (BUN_MAX / lcnt >= rcnt) {
     155             :                 /* in the worst case we have a full cross product */
     156       35438 :                 maxsize = lcnt * rcnt;
     157             :         } else {
     158             :                 /* a BAT cannot grow larger than BUN_MAX */
     159             :                 maxsize = BUN_MAX;
     160             :         }
     161       85711 :         size = estimate == BUN_NONE ? lcnt < rcnt ? lcnt : rcnt : estimate;
     162       85711 :         if (size < INCRSIZE)
     163             :                 size = INCRSIZE;
     164       85711 :         if (size > maxsize)
     165             :                 size = maxsize;
     166       85711 :         if ((rkey | semi | only_misses) & nil_on_miss) {
     167             :                 /* see comment above: each entry left matches exactly
     168             :                  * once */
     169         123 :                 size = maxsize;
     170             :         }
     171       85711 :         if (min_one && size < lcnt)
     172           0 :                 size = lcnt;
     173             : 
     174       85711 :         if (maxsize == 0) {
     175       14761 :                 r1 = BATdense(0, 0, 0);
     176       14639 :                 if (r1 == NULL) {
     177             :                         return BUN_NONE;
     178             :                 }
     179       14639 :                 if (r2p) {
     180         647 :                         r2 = BATdense(0, 0, 0);
     181         661 :                         if (r2 == NULL) {
     182           0 :                                 BBPreclaim(r1);
     183           0 :                                 return BUN_NONE;
     184             :                         }
     185         661 :                         *r2p = r2;
     186             :                 }
     187       14653 :                 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       14653 :                 *r1p = r1;
     199       14653 :                 return 0;
     200             :         }
     201             : 
     202       70950 :         r1 = COLnew(0, TYPE_oid, size, TRANSIENT);
     203       70559 :         if (r1 == NULL) {
     204             :                 return BUN_NONE;
     205             :         }
     206       70559 :         r1->tnil = false;
     207       70559 :         r1->tnonil = true;
     208       70559 :         r1->tkey = true;
     209       70559 :         r1->tsorted = true;
     210       70559 :         r1->trevsorted = true;
     211       70559 :         r1->tseqbase = 0;
     212       70559 :         r1->theap->dirty = true;
     213       70559 :         *r1p = r1;
     214       70559 :         if (r2p) {
     215       31303 :                 r2 = COLnew(0, TYPE_oid, size, TRANSIENT);
     216       31439 :                 if (r2 == NULL) {
     217           0 :                         BBPreclaim(r1);
     218           0 :                         return BUN_NONE;
     219             :                 }
     220       31439 :                 r2->tnil = false;
     221       31439 :                 r2->tnonil = true;
     222       31439 :                 r2->tkey = true;
     223       31439 :                 r2->tsorted = true;
     224       31439 :                 r2->trevsorted = true;
     225       31439 :                 r2->tseqbase = 0;
     226       31439 :                 r2->theap->dirty = true;
     227       31439 :                 *r2p = r2;
     228             :         }
     229       70695 :         if (r3p) {
     230         118 :                 BAT *r3 = COLnew(0, TYPE_bit, size, TRANSIENT);
     231         117 :                 if (r3 == NULL) {
     232           0 :                         BBPreclaim(r1);
     233           0 :                         BBPreclaim(r2);
     234           0 :                         return BUN_NONE;
     235             :                 }
     236         117 :                 r3->tnil = false;
     237         117 :                 r3->tnonil = true;
     238         117 :                 r3->tkey = false;
     239         117 :                 r3->tsorted = false;
     240         117 :                 r3->trevsorted = false;
     241         117 :                 r3->tseqbase = oid_nil;
     242         117 :                 r3->theap->dirty = true;
     243         117 :                 *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   166372759 : maybeextend(BAT *restrict r1, BAT *restrict r2, BAT *restrict r3,
     258             :             BUN cnt, BUN lcur, BUN lcnt, BUN maxsize)
     259             : {
     260   166372759 :         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        2170 :                 BUN newcap = (BUN) (lcnt / (lcnt / 4.0 + lcur * .75) * (BATcount(r1) + cnt));
     267        2170 :                 newcap = (newcap + INCRSIZE - 1) & ~(((BUN) 1 << INCRSIZELOG) - 1);
     268        2170 :                 if (newcap < cnt + BATcount(r1))
     269           0 :                         newcap = cnt + BATcount(r1) + INCRSIZE;
     270             :                 /* if close to maxsize, then just use maxsize */
     271        2170 :                 if (newcap + INCRSIZE > maxsize)
     272         170 :                         newcap = maxsize;
     273             :                 /* make sure heap.free is set properly before
     274             :                  * extending */
     275        2170 :                 BATsetcount(r1, BATcount(r1));
     276        2171 :                 if (BATextend(r1, newcap) != GDK_SUCCEED)
     277             :                         return GDK_FAIL;
     278        2171 :                 if (r2) {
     279        1358 :                         BATsetcount(r2, BATcount(r2));
     280        1358 :                         if (BATextend(r2, newcap) != GDK_SUCCEED)
     281             :                                 return GDK_FAIL;
     282        1358 :                         assert(BATcapacity(r1) == BATcapacity(r2));
     283             :                 }
     284        2171 :                 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      500763 : 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      500763 :         BAT *r1, *r2 = NULL, *r3 = NULL;
     307             : 
     308      500763 :         MT_thread_setalgorithm(__func__);
     309      501161 :         if (lci->ncand == 0 || !(nil_on_miss | only_misses)) {
     310             :                 /* return empty BATs */
     311      482160 :                 if ((r1 = BATdense(0, 0, 0)) == NULL)
     312             :                         return GDK_FAIL;
     313      481144 :                 if (r2p) {
     314      318784 :                         if ((r2 = BATdense(0, 0, 0)) == NULL) {
     315           0 :                                 BBPreclaim(r1);
     316           0 :                                 return GDK_FAIL;
     317             :                         }
     318      320085 :                         *r2p = r2;
     319             :                 }
     320      482445 :                 if (r3p) {
     321       18860 :                         if ((r3 = COLnew(0, TYPE_bit, 0, TRANSIENT)) == NULL) {
     322           0 :                                 BBPreclaim(r1);
     323           0 :                                 BBPreclaim(r2);
     324           0 :                                 return GDK_FAIL;
     325             :                         }
     326       18926 :                         *r3p = r3;
     327             :                 }
     328             :         } else {
     329       19001 :                 r1 = canditer_slice(lci, 0, lci->ncand);
     330       19008 :                 if (r2p) {
     331          22 :                         if ((r2 = BATconstant(0, TYPE_void, &oid_nil, lci->ncand, TRANSIENT)) == NULL) {
     332           0 :                                 BBPreclaim(r1);
     333           0 :                                 return GDK_FAIL;
     334             :                         }
     335          22 :                         *r2p = r2;
     336             :                 }
     337       19008 :                 if (r3p) {
     338          67 :                         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          68 :                         *r3p = r3;
     344             :                 }
     345             :         }
     346      501520 :         *r1p = r1;
     347      501520 :         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       52773 : 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       52773 :         BATiter li = bat_iterator(l);
     369       52807 :         const void *v;
     370       52807 :         BAT *bn = NULL;
     371       52807 :         BAT *r1 = NULL;
     372       52807 :         BAT *r2 = NULL;
     373       52807 :         BUN bncount;
     374             : 
     375       52807 :         assert(lci->ncand > 0);
     376       52807 :         assert(lci->ncand == 1 || (li.sorted && li.revsorted));
     377             : 
     378       52807 :         size_t counter = 0;
     379       52807 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     380             : 
     381       52797 :         MT_thread_setalgorithm(__func__);
     382       52802 :         oid o = canditer_next(lci);
     383       52782 :         v = BUNtail(li, o - l->hseqbase);
     384             : 
     385      102747 :         if (!nil_matches &&
     386       49964 :             (*ATOMcompare(li.type))(v, ATOMnilptr(li.type)) == 0) {
     387             :                 /* NIL doesn't match anything */
     388         196 :                 bat_iterator_end(&li);
     389         196 :                 gdk_return rc = nomatch(r1p, r2p, r3p, l, r, lci, bit_nil, nil_on_miss,
     390             :                                         false, reason, t0);
     391         196 :                 return rc;
     392             :         }
     393             : 
     394       52587 :         bn = BATselect(r, rci->s, v, NULL, true, true, false, false);
     395       52436 :         bat_iterator_end(&li);
     396       52566 :         if (bn == NULL) {
     397             :                 return GDK_FAIL;
     398             :         }
     399       52566 :         bncount = BATcount(bn);
     400       52566 :         if (bncount == 0) {
     401       13996 :                 BBPreclaim(bn);
     402       13971 :                 if (min_one) {
     403           0 :                         GDKerror("not enough matches");
     404           0 :                         return GDK_FAIL;
     405             :                 }
     406       13971 :                 if (!nil_on_miss) {
     407       13789 :                         assert(r3p == NULL);
     408       13789 :                         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       38570 :         if (bncount > 1) {
     416        1928 :                 if (semi)
     417         713 :                         bncount = 1;
     418        1928 :                 if (max_one) {
     419          16 :                         GDKerror("more than one match");
     420          16 :                         goto bailout;
     421             :                 }
     422             :         }
     423       38736 :         r1 = COLnew(0, TYPE_oid, lci->ncand * bncount, TRANSIENT);
     424       38727 :         if (r1 == NULL)
     425           0 :                 goto bailout;
     426       38727 :         r1->tsorted = true;
     427       38727 :         r1->trevsorted = lci->ncand == 1;
     428       38727 :         r1->tseqbase = bncount == 1 && lci->tpe == cand_dense ? o : oid_nil;
     429       38727 :         r1->tkey = bncount == 1;
     430       38727 :         r1->tnil = false;
     431       38727 :         r1->tnonil = true;
     432       38727 :         if (bn == NULL) {
     433             :                 /* left outer join, no match, we're returning nil in r2 */
     434         180 :                 oid *o1p = (oid *) Tloc(r1, 0);
     435         180 :                 BUN p, q = bncount;
     436             : 
     437         180 :                 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         364 :                 do {
     444         364 :                         GDK_CHECK_TIMEOUT(qry_ctx, counter,
     445             :                                           GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     446         727 :                         for (p = 0; p < q; p++) {
     447         363 :                                 *o1p++ = o;
     448             :                         }
     449         364 :                         o = canditer_next(lci);
     450         366 :                 } while (!is_oid_nil(o));
     451             :         } else {
     452       38547 :                 oid *o1p = (oid *) Tloc(r1, 0);
     453       38547 :                 oid *o2p;
     454       38547 :                 BUN p, q = bncount;
     455             : 
     456       38547 :                 if (r2p) {
     457       33061 :                         r2 = COLnew(0, TYPE_oid, lci->ncand * bncount, TRANSIENT);
     458       33085 :                         if (r2 == NULL)
     459           0 :                                 goto bailout;
     460       33085 :                         r2->tsorted = lci->ncand == 1 || bncount == 1;
     461       33085 :                         r2->trevsorted = bncount == 1;
     462       33085 :                         r2->tseqbase = lci->ncand == 1 && BATtdense(bn) ? bn->tseqbase : oid_nil;
     463       33085 :                         r2->tkey = lci->ncand == 1;
     464       33085 :                         r2->tnil = false;
     465       33085 :                         r2->tnonil = true;
     466       33085 :                         *r2p = r2;
     467       33085 :                         o2p = (oid *) Tloc(r2, 0);
     468             :                 } else {
     469             :                         o2p = NULL;
     470             :                 }
     471             : 
     472       38571 :                 if (BATtdense(bn)) {
     473             :                         oid bno = bn->tseqbase;
     474             : 
     475     1341732 :                         do {
     476     1341732 :                                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
     477             :                                                   GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     478     2737175 :                                 for (p = 0; p < q; p++) {
     479     1395443 :                                         *o1p++ = o;
     480             :                                 }
     481     1341732 :                                 if (o2p) {
     482      432309 :                                         for (p = 0; p < q; p++) {
     483      242964 :                                                 *o2p++ = bno + p;
     484             :                                         }
     485             :                                 }
     486     1341732 :                                 o = canditer_next(lci);
     487     1341726 :                         } while (!is_oid_nil(o));
     488             :                 } else {
     489         292 :                         const oid *bnp = (const oid *) Tloc(bn, 0);
     490             : 
     491      151087 :                         do {
     492      151087 :                                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
     493             :                                                   GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     494     6314931 :                                 for (p = 0; p < q; p++) {
     495     6163844 :                                         *o1p++ = o;
     496             :                                 }
     497      151087 :                                 if (o2p) {
     498     6437900 :                                         for (p = 0; p < q; p++) {
     499     6270680 :                                                 *o2p++ = bnp[p];
     500             :                                         }
     501             :                                 }
     502      151087 :                                 o = canditer_next(lci);
     503      151081 :                         } while (!is_oid_nil(o));
     504             :                 }
     505       38559 :                 if (r2)
     506       33069 :                         BATsetcount(r2, lci->ncand * bncount);
     507             :         }
     508       38742 :         BATsetcount(r1, lci->ncand * bncount);
     509       38743 :         *r1p = r1;
     510       38743 :         BAT *r3 = NULL;
     511       38743 :         if (r3p) {
     512         227 :                 bit mark;
     513         227 :                 if (bn) {
     514             :                         /* there is a match */
     515          47 :                         mark = 1;
     516         180 :                 } else if (r->tnonil) {
     517             :                         /* no match, no NIL in r */
     518         172 :                         mark = 0;
     519             :                 } else {
     520             :                         /* no match, search for NIL in r */
     521           8 :                         BAT *n = BATselect(r, rci->s, ATOMnilptr(r->ttype), NULL, true, true, false, false);
     522           9 :                         if (n == NULL)
     523           0 :                                 goto bailout;
     524           9 :                         mark = BATcount(n) == 0 ? 0 : bit_nil;
     525           9 :                         BBPreclaim(n);
     526             :                 }
     527         228 :                 r3 = BATconstant(0, TYPE_bit, &mark, lci->ncand, TRANSIENT);
     528         229 :                 if (r3 == NULL)
     529           0 :                         goto bailout;
     530         229 :                 *r3p = r3;
     531             :         }
     532       38745 :         BBPreclaim(bn);
     533       38723 :         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          16 :   bailout:
     548          16 :         BBPreclaim(bn);
     549          16 :         BBPreclaim(r1);
     550          16 :         BBPreclaim(r2);
     551          16 :         if (r2p)
     552          15 :                 *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       26762 : 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       26762 :         oid lo, hi;
     577       26762 :         BUN i;
     578       26762 :         oid o, *o1p = NULL, *o2p = NULL;
     579       26762 :         bit *m3p = NULL;
     580       26762 :         BAT *r1 = NULL, *r2 = NULL, *r3 = NULL;
     581       26762 :         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       38591 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
     588       26762 :         assert(r->tsorted || r->trevsorted);
     589       26762 :         assert(BATcount(l) > 0);
     590       26762 :         assert(rci->tpe == cand_dense);
     591       26762 :         assert(BATcount(r) > 0);
     592             : 
     593       26762 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     594             : 
     595       26778 :         MT_thread_setalgorithm(__func__);
     596             :         /* figure out range [lo..hi) of values in r that we need to match */
     597       26802 :         lo = r->tseqbase;
     598       26802 :         hi = lo + BATcount(r);
     599             :         /* restrict [lo..hi) range further using candidate list */
     600       26802 :         if (rci->seq > r->hseqbase)
     601           0 :                 lo += rci->seq - r->hseqbase;
     602       26802 :         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       26802 :         if (!nil_on_miss) {
     607       26802 :                 assert(r3p == NULL);
     608       26802 :                 r1 = BATselect(l, lci->s, &lo, &hi, true, false, only_misses, false);
     609       26708 :                 if (r1 == NULL)
     610             :                         return GDK_FAIL;
     611       26708 :                 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       26708 :                 *r1p = r1;
     631       26708 :                 if (r2p == NULL)
     632       25538 :                         goto doreturn2;
     633        1170 :                 if (BATcount(r1) == 0) {
     634          52 :                         r2 = BATdense(0, 0, 0);
     635          52 :                         if (r2 == NULL) {
     636           0 :                                 BBPreclaim(r1);
     637           0 :                                 return GDK_FAIL;
     638             :                         }
     639        1118 :                 } else if (BATtdense(r1) && BATtdense(l)) {
     640          83 :                         r2 = BATdense(0, l->tseqbase + r1->tseqbase - l->hseqbase + r->hseqbase - r->tseqbase, BATcount(r1));
     641          83 :                         if (r2 == NULL) {
     642           0 :                                 BBPreclaim(r1);
     643           0 :                                 return GDK_FAIL;
     644             :                         }
     645             :                 } else {
     646        1035 :                         r2 = COLnew(0, TYPE_oid, BATcount(r1), TRANSIENT);
     647        1054 :                         if (r2 == NULL) {
     648           0 :                                 BBPreclaim(r1);
     649           0 :                                 return GDK_FAIL;
     650             :                         }
     651        1054 :                         BATiter li = bat_iterator(l);
     652        1044 :                         const oid *lp = (const oid *) li.base;
     653        1044 :                         const oid *o1p = (const oid *) Tloc(r1, 0);
     654        1044 :                         oid *o2p = (oid *) Tloc(r2, 0);
     655        1044 :                         hi = BATcount(r1);
     656        1044 :                         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        1044 :                         } else if (BATtdense(r1)) {
     661         482 :                                 lo = r1->tseqbase - l->hseqbase;
     662         482 :                                 if (r->tseqbase == r->hseqbase) {
     663         473 :                                         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         562 :                         } 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    47985689 :                                 for (o = 0; o < hi; o++) {
     676    47985127 :                                         o2p[o] = lp[o1p[o] - l->hseqbase] - r->tseqbase + r->hseqbase;
     677             :                                 }
     678             :                         }
     679        1044 :                         r2->tkey = li.key;
     680        1044 :                         r2->tsorted = li.sorted;
     681        1044 :                         r2->trevsorted = li.revsorted;
     682        1044 :                         bat_iterator_end(&li);
     683        1048 :                         r2->tnil = false;
     684        1048 :                         r2->tnonil = true;
     685        1048 :                         BATsetcount(r2, BATcount(r1));
     686             :                 }
     687        1184 :                 *r2p = r2;
     688        1184 :                 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       26722 :         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        8873 : 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        8873 :         BAT *r1, *r2;
    1028        8873 :         BUN lstart, lend, lcnt;
    1029        8873 :         BUN rstart, rend;
    1030        8873 :         BUN lscan, rscan;       /* opportunistic scan window */
    1031        8873 :         BUN maxsize;
    1032        8873 :         const int *lvals, *rvals;
    1033        8873 :         int v;
    1034        8873 :         BUN nl, nr;
    1035        8873 :         oid lv;
    1036        8873 :         BUN i;
    1037        8873 :         BATiter li = bat_iterator(l);
    1038        8898 :         BATiter ri = bat_iterator(r);
    1039             : 
    1040       26700 :         assert(ATOMtype(li.type) == ATOMtype(ri.type));
    1041        8899 :         assert(ri.sorted || ri.revsorted);
    1042             : 
    1043        8899 :         MT_thread_setalgorithm(__func__);
    1044        8897 :         lstart = rstart = 0;
    1045        8897 :         lend = BATcount(l);
    1046        8897 :         lcnt = lend - lstart;
    1047        8897 :         rend = BATcount(r);
    1048        8897 :         lvals = (const int *) li.base;
    1049        8897 :         rvals = (const int *) ri.base;
    1050        8897 :         size_t counter = 0;
    1051        8897 :         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        8893 :         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        8849 :         if ((maxsize = joininitresults(r1p, r2p, NULL, BATcount(l), BATcount(r),
    1066        8893 :                                        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        8849 :         r1 = *r1p;
    1073        8849 :         r2 = r2p ? *r2p : NULL;
    1074             : 
    1075             :         /* determine opportunistic scan window for l and r */
    1076       52960 :         for (nl = lend - lstart, lscan = 4; nl > 0; lscan++)
    1077       44111 :                 nl >>= 1;
    1078       67581 :         for (nr = rend - rstart, rscan = 4; nr > 0; rscan++)
    1079       58732 :                 nr >>= 1;
    1080             : 
    1081        8849 :         if (!nil_matches) {
    1082             :                 /* skip over nils at the start of the columns */
    1083        5812 :                 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        5812 :                         while (is_int_nil(lvals[lstart]))
    1088           0 :                                 lstart++;
    1089             :                 }
    1090        5812 :                 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        5812 :                         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      376797 :         while (lstart < lend && rstart < rend) {
    1101      370636 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    1102             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    1103             : 
    1104      370636 :                 v = rvals[rstart];
    1105             : 
    1106      370636 :                 if (lscan < lend - lstart && lvals[lstart + lscan] < v) {
    1107        2049 :                         lstart = binsearch_int(NULL, 0, lvals, lstart + lscan,
    1108             :                                                lend - 1, v, 1, 0);
    1109             :                 } else {
    1110             :                         /* scan l for v */
    1111      376140 :                         while (lstart < lend && lvals[lstart] < v)
    1112        7553 :                                 lstart++;
    1113             :                 }
    1114      372019 :                 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      371136 :                 nl = 1;         /* we'll match (at least) one in l */
    1131      371136 :                 nr = 0;         /* maybe we won't match anything in r */
    1132      371136 :                 v = lvals[lstart];
    1133      371136 :                 if (li.key) {
    1134             :                         /* if l is key, there is a single value */
    1135       56315 :                         lstart++;
    1136      314821 :                 } else if (lscan < lend - lstart &&
    1137      307389 :                            v == lvals[lstart + lscan]) {
    1138             :                         /* lots of equal values: use binary search to
    1139             :                          * find end */
    1140       25612 :                         nl = binsearch_int(NULL, 0, lvals, lstart + lscan,
    1141             :                                            lend - 1, v, 1, 1);
    1142       25632 :                         nl -= lstart;
    1143       25632 :                         lstart += nl;
    1144             :                 } else {
    1145             :                         /* just scan */
    1146     1399452 :                         while (++lstart < lend && v == lvals[lstart])
    1147     1110243 :                                 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      371156 :                 if (rscan < rend - rstart && rvals[rstart + rscan] < v) {
    1170             :                         /* value too far away in r: use binary
    1171             :                          * search */
    1172       20007 :                         rstart = binsearch_int(NULL, 0, rvals, rstart + rscan,
    1173             :                                                rend - 1, v, 1, 0);
    1174             :                 } else {
    1175             :                         /* scan r for v */
    1176      379257 :                         while (rstart < rend && rvals[rstart] < v)
    1177       28108 :                                 rstart++;
    1178             :                 }
    1179      373716 :                 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      371894 :                 if (ri.key) {
    1190      168755 :                         if (rstart < rend && v == rvals[rstart]) {
    1191      168666 :                                 nr = 1;
    1192      168666 :                                 rstart++;
    1193             :                         }
    1194      203139 :                 } else if (rscan < rend - rstart &&
    1195      201942 :                            v == rvals[rstart + rscan]) {
    1196             :                         /* range too large: use binary search */
    1197       70879 :                         nr = binsearch_int(NULL, 0, rvals, rstart + rscan,
    1198             :                                            rend - 1, v, 1, 1);
    1199       70917 :                         nr -= rstart;
    1200       70917 :                         rstart += nr;
    1201             :                 } else {
    1202             :                         /* scan r for end of range */
    1203     1065629 :                         while (rstart < rend && v == rvals[rstart]) {
    1204      933369 :                                 nr++;
    1205      933369 :                                 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      371843 :                 if (nr == 0) {
    1212             :                         /* no entries in r found */
    1213          56 :                         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      371876 :                 if (maybeextend(r1, r2, NULL, nl * nr, lstart, lend, maxsize) != GDK_SUCCEED)
    1218           0 :                         goto bailout;
    1219             : 
    1220             :                 /* maintain properties */
    1221      367892 :                 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      247054 :                         if (r2) {
    1226      214173 :                                 r2->tkey = false;
    1227      214173 :                                 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      247054 :                         r1->trevsorted = false;
    1233             :                 }
    1234      367892 :                 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      161899 :                         r1->tkey = false;
    1239      161899 :                         r1->tseqbase = oid_nil;
    1240             :                         /* multiple different values will be inserted
    1241             :                          * in r2 (in order), so not reverse ordered
    1242             :                          * anymore */
    1243      161899 :                         if (r2) {
    1244      110788 :                                 r2->trevsorted = false;
    1245      110788 :                                 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       84299 :                                         r2->tsorted = false;
    1253             :                                 }
    1254             :                         }
    1255             :                 }
    1256      367892 :                 if (BATcount(r1) > 0) {
    1257             :                         /* a new, higher value will be inserted into
    1258             :                          * r1, so r1 is not reverse ordered anymore */
    1259      361314 :                         r1->trevsorted = false;
    1260             :                         /* a new higher value will be added to r2 */
    1261      361314 :                         if (r2) {
    1262      297064 :                                 r2->trevsorted = false;
    1263             :                         }
    1264      361314 :                         if (BATtdense(r1) &&
    1265      193887 :                             ((oid *) r1->theap->base)[r1->batCount - 1] + 1 != l->hseqbase + lstart - nl) {
    1266         160 :                                 r1->tseqbase = oid_nil;
    1267             :                         }
    1268             :                 }
    1269             : 
    1270      367892 :                 if (r2 &&
    1271      302686 :                     BATcount(r2) > 0 &&
    1272      296980 :                     BATtdense(r2) &&
    1273       74476 :                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != r->hseqbase + rstart - nr) {
    1274         728 :                         r2->tseqbase = oid_nil;
    1275             :                 }
    1276             : 
    1277             :                 /* insert values */
    1278      367892 :                 lv = l->hseqbase + lstart - nl;
    1279    15765243 :                 for (i = 0; i < nl; i++) {
    1280             :                         BUN j;
    1281             : 
    1282   113088283 :                         for (j = 0; j < nr; j++) {
    1283    97690932 :                                 APPEND(r1, lv);
    1284             :                         }
    1285    15397351 :                         if (r2) {
    1286    15227075 :                                 oid rv = r->hseqbase + rstart - nr;
    1287             : 
    1288   103590977 :                                 for (j = 0; j < nr; j++) {
    1289    88363902 :                                         APPEND(r2, rv);
    1290    88363902 :                                         rv++;
    1291             :                                 }
    1292             :                         }
    1293    15397351 :                         lv++;
    1294             :                 }
    1295             :         }
    1296             :         /* also set other bits of heap to correct value to indicate size */
    1297        8866 :         BATsetcount(r1, BATcount(r1));
    1298        8826 :         if (r2) {
    1299        6785 :                 BATsetcount(r2, BATcount(r2));
    1300        6789 :                 assert(BATcount(r1) == BATcount(r2));
    1301             :         }
    1302        8830 :         if (BATcount(r1) > 0) {
    1303        6806 :                 if (BATtdense(r1))
    1304        5309 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    1305        6806 :                 if (r2 && BATtdense(r2))
    1306        3737 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    1307             :         } else {
    1308        2024 :                 r1->tseqbase = 0;
    1309        2024 :                 if (r2) {
    1310         976 :                         r2->tseqbase = 0;
    1311             :                 }
    1312             :         }
    1313        8830 :         bat_iterator_end(&li);
    1314        8887 :         bat_iterator_end(&ri);
    1315        8851 :         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         261 : 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         261 :         BAT *r1, *r2;
    1342         261 :         BUN lstart, lend, lcnt;
    1343         261 :         BUN rstart, rend;
    1344         261 :         BUN lscan, rscan;       /* opportunistic scan window */
    1345         261 :         BUN maxsize;
    1346         261 :         const lng *lvals, *rvals;
    1347         261 :         lng v;
    1348         261 :         BUN nl, nr;
    1349         261 :         oid lv;
    1350         261 :         BUN i;
    1351         261 :         BATiter li = bat_iterator(l);
    1352         261 :         BATiter ri = bat_iterator(r);
    1353             : 
    1354         783 :         assert(ATOMtype(li.type) == ATOMtype(ri.type));
    1355         261 :         assert(ri.sorted || ri.revsorted);
    1356             : 
    1357         261 :         MT_thread_setalgorithm(__func__);
    1358         261 :         lstart = rstart = 0;
    1359         261 :         lend = BATcount(l);
    1360         261 :         lcnt = lend - lstart;
    1361         261 :         rend = BATcount(r);
    1362         261 :         lvals = (const lng *) li.base;
    1363         261 :         rvals = (const lng *) ri.base;
    1364         261 :         size_t counter = 0;
    1365         261 :         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         261 :         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         261 :         if ((maxsize = joininitresults(r1p, r2p, NULL, BATcount(l), BATcount(r),
    1380         261 :                                        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         261 :         r1 = *r1p;
    1387         261 :         r2 = r2p ? *r2p : NULL;
    1388             : 
    1389             :         /* determine opportunistic scan window for l and r */
    1390        1819 :         for (nl = lend - lstart, lscan = 4; nl > 0; lscan++)
    1391        1558 :                 nl >>= 1;
    1392        1808 :         for (nr = rend - rstart, rscan = 4; nr > 0; rscan++)
    1393        1547 :                 nr >>= 1;
    1394             : 
    1395         261 :         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      414907 :         while (lstart < lend && rstart < rend) {
    1415      414755 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    1416             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    1417      414754 :                 v = rvals[rstart];
    1418             : 
    1419      414754 :                 if (lscan < lend - lstart && lvals[lstart + lscan] < v) {
    1420         954 :                         lstart = binsearch_lng(NULL, 0, lvals, lstart + lscan,
    1421             :                                                lend - 1, v, 1, 0);
    1422             :                 } else {
    1423             :                         /* scan l for v */
    1424      493336 :                         while (lstart < lend && lvals[lstart] < v)
    1425       79536 :                                 lstart++;
    1426             :                 }
    1427      414267 :                 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      414188 :                 nl = 1;         /* we'll match (at least) one in l */
    1444      414188 :                 nr = 0;         /* maybe we won't match anything in r */
    1445      414188 :                 v = lvals[lstart];
    1446      414188 :                 if (li.key) {
    1447             :                         /* if l is key, there is a single value */
    1448      369807 :                         lstart++;
    1449       44381 :                 } else if (lscan < lend - lstart &&
    1450       44277 :                            v == lvals[lstart + lscan]) {
    1451             :                         /* lots of equal values: use binary search to
    1452             :                          * find end */
    1453         395 :                         nl = binsearch_lng(NULL, 0, lvals, lstart + lscan,
    1454             :                                            lend - 1, v, 1, 1);
    1455         395 :                         nl -= lstart;
    1456         395 :                         lstart += nl;
    1457             :                 } else {
    1458             :                         /* just scan */
    1459       68516 :                         while (++lstart < lend && v == lvals[lstart])
    1460       24530 :                                 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      414188 :                 if (rscan < rend - rstart && rvals[rstart + rscan] < v) {
    1483             :                         /* value too far away in r: use binary
    1484             :                          * search */
    1485        2261 :                         rstart = binsearch_lng(NULL, 0, rvals, rstart + rscan,
    1486             :                                                rend - 1, v, 1, 0);
    1487             :                 } else {
    1488             :                         /* scan r for v */
    1489     1488056 :                         while (rstart < rend && rvals[rstart] < v)
    1490     1076129 :                                 rstart++;
    1491             :                 }
    1492      414368 :                 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      414340 :                 if (ri.key) {
    1503      376736 :                         if (rstart < rend && v == rvals[rstart]) {
    1504       81995 :                                 nr = 1;
    1505       81995 :                                 rstart++;
    1506             :                         }
    1507       37604 :                 } else if (rscan < rend - rstart &&
    1508       37556 :                            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       90411 :                         while (rstart < rend && v == rvals[rstart]) {
    1517       52807 :                                 nr++;
    1518       52807 :                                 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      119599 :                 if (nr == 0) {
    1525             :                         /* no entries in r found */
    1526      294736 :                         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      119604 :                 if (maybeextend(r1, r2, NULL, nl * nr, lstart, lend, maxsize) != GDK_SUCCEED)
    1531           0 :                         goto bailout;
    1532             : 
    1533             :                 /* maintain properties */
    1534      119910 :                 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        6628 :                         if (r2) {
    1539        1806 :                                 r2->tkey = false;
    1540        1806 :                                 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        6628 :                         r1->trevsorted = false;
    1546             :                 }
    1547      119910 :                 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        4429 :                         r1->tkey = false;
    1552        4429 :                         r1->tseqbase = oid_nil;
    1553             :                         /* multiple different values will be inserted
    1554             :                          * in r2 (in order), so not reverse ordered
    1555             :                          * anymore */
    1556        4429 :                         if (r2) {
    1557        4429 :                                 r2->trevsorted = false;
    1558        4429 :                                 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      119910 :                 if (BATcount(r1) > 0) {
    1570             :                         /* a new, higher value will be inserted into
    1571             :                          * r1, so r1 is not reverse ordered anymore */
    1572      119392 :                         r1->trevsorted = false;
    1573             :                         /* a new higher value will be added to r2 */
    1574      119392 :                         if (r2) {
    1575      113004 :                                 r2->trevsorted = false;
    1576             :                         }
    1577      119392 :                         if (BATtdense(r1) &&
    1578       52831 :                             ((oid *) r1->theap->base)[r1->batCount - 1] + 1 != l->hseqbase + lstart - nl) {
    1579          68 :                                 r1->tseqbase = oid_nil;
    1580             :                         }
    1581             :                 }
    1582             : 
    1583      119910 :                 if (r2 &&
    1584      113406 :                     BATcount(r2) > 0 &&
    1585      112671 :                     BATtdense(r2) &&
    1586       51685 :                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != r->hseqbase + rstart - nr) {
    1587          36 :                         r2->tseqbase = oid_nil;
    1588             :                 }
    1589             : 
    1590             :                 /* insert values */
    1591      119910 :                 lv = l->hseqbase + lstart - nl;
    1592      268474 :                 for (i = 0; i < nl; i++) {
    1593             :                         BUN j;
    1594             : 
    1595      310993 :                         for (j = 0; j < nr; j++) {
    1596      162429 :                                 APPEND(r1, lv);
    1597             :                         }
    1598      148564 :                         if (r2) {
    1599      131829 :                                 oid rv = r->hseqbase + rstart - nr;
    1600             : 
    1601      277497 :                                 for (j = 0; j < nr; j++) {
    1602      145668 :                                         APPEND(r2, rv);
    1603      145668 :                                         rv++;
    1604             :                                 }
    1605             :                         }
    1606      148564 :                         lv++;
    1607             :                 }
    1608             :         }
    1609             :         /* also set other bits of heap to correct value to indicate size */
    1610         259 :         BATsetcount(r1, BATcount(r1));
    1611         260 :         if (r2) {
    1612         234 :                 BATsetcount(r2, BATcount(r2));
    1613         233 :                 assert(BATcount(r1) == BATcount(r2));
    1614             :         }
    1615         259 :         if (BATcount(r1) > 0) {
    1616         223 :                 if (BATtdense(r1))
    1617         132 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    1618         223 :                 if (r2 && BATtdense(r2))
    1619         129 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    1620             :         } else {
    1621          36 :                 r1->tseqbase = 0;
    1622          36 :                 if (r2) {
    1623          22 :                         r2->tseqbase = 0;
    1624             :                 }
    1625             :         }
    1626         259 :         bat_iterator_end(&li);
    1627         259 :         bat_iterator_end(&ri);
    1628         260 :         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, swapped, and reason are only for debugging (ALGOMASK set in
    1939             :  * GDKdebug).
    1940             :  */
    1941             : static gdk_return
    1942       17257 : mergejoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
    1943             :           struct canditer *restrict lci, struct canditer *restrict rci,
    1944             :           bool nil_matches, bool nil_on_miss, bool semi, bool only_misses,
    1945             :           bool not_in, bool max_one, bool min_one, BUN estimate,
    1946             :           lng t0, bool swapped,
    1947             :           const char *reason)
    1948             : {
    1949             :         /* [lr]scan determine how far we look ahead in l/r in order to
    1950             :          * decide whether we want to do a binary search or a scan */
    1951       17257 :         BUN lscan, rscan;
    1952       17257 :         const void *lvals, *rvals; /* the values of l/r (NULL if dense) */
    1953       17257 :         const char *lvars, *rvars; /* the indirect values (NULL if fixed size) */
    1954       17257 :         const void *nil = ATOMnilptr(l->ttype);
    1955       17257 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    1956       17257 :         const void *v;          /* points to value under consideration */
    1957       17257 :         const void *prev = NULL;
    1958       17257 :         BUN nl, nr;
    1959       17257 :         bool insert_nil;
    1960             :         /* equal_order is set if we can scan both BATs in the same
    1961             :          * order, so when both are sorted or both are reverse sorted
    1962             :          * -- important to know in order to skip over values; if l is
    1963             :          * not sorted, this must be set to true and we will always do a
    1964             :          * binary search on all of r */
    1965       17257 :         bool equal_order;
    1966             :         /* [lr]ordering is either 1 or -1 depending on the order of
    1967             :          * l/r: it determines the comparison function used */
    1968       17257 :         int lordering, rordering;
    1969       17257 :         oid lv;
    1970       17257 :         BUN i, j;               /* counters */
    1971       17257 :         oid lval = oid_nil, rval = oid_nil; /* temporary space to point v to */
    1972       17257 :         struct canditer llci, rrci;
    1973       17257 :         struct canditer *mlci, xlci;
    1974       17257 :         struct canditer *mrci, xrci;
    1975             : 
    1976       17257 :         if (lci->tpe == cand_dense && lci->ncand == BATcount(l) &&
    1977       17185 :             rci->tpe == cand_dense && rci->ncand == BATcount(r) &&
    1978       16509 :             !nil_on_miss && !semi && !max_one && !min_one && !only_misses &&
    1979       11613 :             !not_in &&
    1980        9290 :             l->tsorted && r->tsorted) {
    1981             :                 /* special cases with far fewer options */
    1982        9232 :                 if (complex_cand(r))
    1983           0 :                         return mergejoin_cand(r1p, r2p, l, r, nil_matches,
    1984             :                                               estimate, t0, swapped, __func__);
    1985       18388 :                 switch (ATOMbasetype(l->ttype)) {
    1986        8881 :                 case TYPE_int:
    1987        8881 :                         return mergejoin_int(r1p, r2p, l, r, nil_matches,
    1988             :                                              estimate, t0, swapped, __func__);
    1989         261 :                 case TYPE_lng:
    1990         261 :                         return mergejoin_lng(r1p, r2p, l, r, nil_matches,
    1991             :                                              estimate, t0, swapped, __func__);
    1992             :                 }
    1993             :         }
    1994             : 
    1995       24214 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    1996        8115 :         assert(r->tsorted || r->trevsorted);
    1997             : 
    1998        8115 :         size_t counter = 0;
    1999        8115 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2000             : 
    2001        8110 :         BATiter li = bat_iterator(l);
    2002        8112 :         BATiter ri = bat_iterator(r);
    2003        8116 :         MT_thread_setalgorithm(__func__);
    2004        8109 :         if (BATtvoid(l)) {
    2005             :                 /* l->ttype == TYPE_void && is_oid_nil(l->tseqbase) is
    2006             :                  * handled by selectjoin */
    2007          72 :                 assert(!is_oid_nil(l->tseqbase));
    2008          72 :                 canditer_init(&llci, NULL, l);
    2009          72 :                 lvals = NULL;
    2010             :         } else {
    2011        8037 :                 lvals = li.base;                              /* non NULL */
    2012        8037 :                 llci = (struct canditer) {.tpe = cand_dense}; /* not used */
    2013             :         }
    2014        8111 :         rrci = (struct canditer) {.tpe = cand_dense};
    2015        8111 :         if (BATtvoid(r)) {
    2016          53 :                 if (!is_oid_nil(r->tseqbase))
    2017          53 :                         canditer_init(&rrci, NULL, r);
    2018             :                 rvals = NULL;
    2019             :         } else {
    2020        8058 :                 rvals = ri.base;
    2021             :         }
    2022        8104 :         if (li.vh && li.type) {
    2023         171 :                 assert(ri.vh && ri.type);
    2024         171 :                 lvars = li.vh->base;
    2025         171 :                 rvars = ri.vh->base;
    2026             :         } else {
    2027        7933 :                 assert(ri.vh == NULL || ri.type == TYPE_void);
    2028             :                 lvars = rvars = NULL;
    2029             :         }
    2030             :         /* if the var pointer is not NULL, then so is the val pointer */
    2031        8104 :         assert(lvars == NULL || lvals != NULL);
    2032        8104 :         assert(rvars == NULL || rvals != NULL);
    2033             : 
    2034        8104 :         const bool rhasnil = !ri.nonil &&
    2035         982 :                 ((BATtvoid(r) && r->tseqbase == oid_nil) ||
    2036         982 :                  (rvals && cmp(nil, VALUE(r, (ri.sorted ? rci->seq : canditer_last(rci)) - r->hseqbase)) == 0));
    2037          10 :         const bit defmark = rhasnil ? bit_nil : 0;
    2038             : 
    2039        8104 :         if (not_in && (rhasnil || (BATtvoid(l) && l->tseqbase == oid_nil))) {
    2040           0 :                 bat_iterator_end(&li);
    2041           0 :                 bat_iterator_end(&ri);
    2042           0 :                 return nomatch(r1p, r2p, r3p, l, r, lci, defmark, false, false,
    2043             :                                __func__, t0);
    2044             :         }
    2045             : 
    2046        8104 :         if ((!nil_matches &&
    2047        7799 :              ((li.type == TYPE_void && is_oid_nil(l->tseqbase)) ||
    2048        7799 :               (ri.type == TYPE_void && is_oid_nil(r->tseqbase)))) ||
    2049        8104 :             (li.type == TYPE_void && is_oid_nil(l->tseqbase) &&
    2050           0 :              (ri.nonil ||
    2051           0 :               (ri.type == TYPE_void && !is_oid_nil(r->tseqbase)))) ||
    2052        8104 :             (ri.type == TYPE_void && is_oid_nil(r->tseqbase) &&
    2053           0 :              (li.nonil ||
    2054           0 :               (li.type == TYPE_void && !is_oid_nil(l->tseqbase))))) {
    2055             :                 /* there are no matches */
    2056           0 :                 bat_iterator_end(&li);
    2057           0 :                 bat_iterator_end(&ri);
    2058           0 :                 return nomatch(r1p, r2p, r3p, l, r, lci, defmark,
    2059             :                                nil_on_miss, only_misses, __func__, t0);
    2060             :         }
    2061             : 
    2062       16171 :         BUN maxsize = joininitresults(r1p, r2p, r3p, lci->ncand, rci->ncand,
    2063        8104 :                                       li.key, ri.key, semi | max_one,
    2064             :                                       nil_on_miss, only_misses, min_one,
    2065             :                                       estimate);
    2066        8067 :         if (maxsize == BUN_NONE) {
    2067           0 :                 bat_iterator_end(&li);
    2068           0 :                 bat_iterator_end(&ri);
    2069           0 :                 return GDK_FAIL;
    2070             :         }
    2071        8067 :         BAT *r1 = *r1p;
    2072        8067 :         BAT *r2 = r2p ? *r2p : NULL;
    2073        8067 :         BAT *r3 = r3p ? *r3p : NULL;
    2074             : 
    2075        8067 :         if (lci->tpe == cand_mask) {
    2076           0 :                 mlci = lci;
    2077           0 :                 canditer_init(&xlci, l, NULL);
    2078           0 :                 lci = &xlci;
    2079             :         } else {
    2080        8067 :                 mlci = NULL;
    2081        8067 :                 xlci = (struct canditer) {.tpe = cand_dense}; /* not used */
    2082             :         }
    2083        8067 :         if (rci->tpe == cand_mask) {
    2084           0 :                 mrci = rci;
    2085           0 :                 canditer_init(&xrci, r, NULL);
    2086           0 :                 rci = &xrci;
    2087             :         } else {
    2088        8067 :                 mrci = NULL;
    2089        8067 :                 xrci = (struct canditer) {.tpe = cand_dense}; /* not used */
    2090             :         }
    2091             : 
    2092        8067 :         if (li.sorted || li.revsorted) {
    2093        5568 :                 equal_order = (li.sorted && ri.sorted) ||
    2094         387 :                         (li.revsorted && ri.revsorted &&
    2095         114 :                          !BATtvoid(l) && !BATtvoid(r));
    2096        5568 :                 lordering = li.sorted && (ri.sorted || !equal_order) ? 1 : -1;
    2097        5475 :                 rordering = equal_order ? lordering : -lordering;
    2098        5568 :                 if (!li.nonil && !nil_matches && !nil_on_miss && lvals != NULL) {
    2099             :                         /* find first non-nil */
    2100         541 :                         nl = binsearch(NULL, 0, li.type, lvals, lvars, li.width, 0, BATcount(l), nil, li.sorted ? 1 : -1, li.sorted ? 1 : 0);
    2101         480 :                         nl = canditer_search(lci, nl + l->hseqbase, true);
    2102         480 :                         if (li.sorted) {
    2103         428 :                                 canditer_setidx(lci, nl);
    2104          52 :                         } else if (li.revsorted) {
    2105          52 :                                 lci->ncand = nl;
    2106             :                         }
    2107             :                 }
    2108             :                 /* determine opportunistic scan window for l */
    2109       11118 :                 lscan = 4 + ilog2(lci->ncand);
    2110             :         } else {
    2111             :                 /* if l not sorted, we will always use binary search
    2112             :                  * on r */
    2113        2499 :                 assert(!BATtvoid(l)); /* void is always sorted */
    2114        2499 :                 lscan = 0;
    2115        2499 :                 equal_order = true;
    2116        2499 :                 lordering = 1;
    2117        2499 :                 rordering = ri.sorted ? 1 : -1;
    2118             :         }
    2119             :         /* determine opportunistic scan window for r; if l is not
    2120             :          * sorted this is only used to find range of equal values */
    2121        8058 :         rscan = 4 + ilog2(rci->ncand);
    2122             : 
    2123        8058 :         if (!equal_order) {
    2124             :                 /* we go through r backwards */
    2125         283 :                 canditer_setidx(rci, rci->ncand);
    2126             :         }
    2127             :         /* At this point the various variables that help us through
    2128             :          * the algorithm have been set.  The table explains them.  The
    2129             :          * first two columns are the inputs, the next three columns
    2130             :          * are the variables, the final two columns indicate how the
    2131             :          * variables can be used.
    2132             :          *
    2133             :          * l/r    sl/sr | vals  cand  off | result   value being matched
    2134             :          * -------------+-----------------+----------------------------------
    2135             :          * dense  NULL  | NULL  NULL  set | i        off==nil?nil:i+off
    2136             :          * dense  dense | NULL  NULL  set | i        off==nil?nil:i+off
    2137             :          * dense  set   | NULL  set   set | cand[i]  off==nil?nil:cand[i]+off
    2138             :          * set    NULL  | set   NULL  0   | i        vals[i]
    2139             :          * set    dense | set   NULL  0   | i        vals[i]
    2140             :          * set    set   | set   set   0   | cand[i]  vals[cand[i]]
    2141             :          *
    2142             :          * If {l,r}off is lng_nil, all values in the corresponding bat
    2143             :          * are oid_nil because the bat has type VOID and the tseqbase
    2144             :          * is nil.
    2145             :          */
    2146             : 
    2147             : 
    2148             :         /* Before we start adding values to r1 and r2, the properties
    2149             :          * are as follows:
    2150             :          * tseqbase - 0
    2151             :          * tkey - true
    2152             :          * tsorted - true
    2153             :          * trevsorted - true
    2154             :          * tnil - false
    2155             :          * tnonil - true
    2156             :          * We will modify these as we go along.
    2157             :          */
    2158      581170 :         while (lci->next < lci->ncand) {
    2159      575550 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    2160             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    2161      575550 :                 bit mark = defmark;
    2162      575550 :                 if (lscan == 0) {
    2163             :                         /* always search r completely */
    2164      306179 :                         assert(equal_order);
    2165      306179 :                         canditer_reset(rci);
    2166             :                 } else {
    2167             :                         /* If l is sorted (lscan > 0), we look at the
    2168             :                          * next value in r to see whether we can jump
    2169             :                          * over a large section of l using binary
    2170             :                          * search.  We do this by looking ahead in l
    2171             :                          * (lscan far, to be precise) and seeing if
    2172             :                          * the value there is still too "small"
    2173             :                          * (definition depends on sort order of l).
    2174             :                          * If it is, we use binary search on l,
    2175             :                          * otherwise we scan l for the next position
    2176             :                          * with a value greater than or equal to the
    2177             :                          * value in r.
    2178             :                          * The next value to match in r is the first
    2179             :                          * if equal_order is set, the last
    2180             :                          * otherwise.
    2181             :                          * When skipping over values in l, we count
    2182             :                          * how many we skip in nlx.  We need this in
    2183             :                          * case only_misses or nil_on_miss is set, and
    2184             :                          * to properly set the dense property in the
    2185             :                          * first output BAT. */
    2186      269371 :                         BUN nlx = 0; /* number of non-matching values in l */
    2187             : 
    2188      269371 :                         if (equal_order) {
    2189      268189 :                                 if (rci->next == rci->ncand)
    2190             :                                         v = NULL; /* no more values */
    2191      265872 :                                 else if (mrci) {
    2192           0 :                                         oid rv = canditer_mask_next(mrci, canditer_peek(rci), true);
    2193           0 :                                         v = rv == oid_nil ? NULL : VALUE(r, rv - r->hseqbase);
    2194             :                                 } else
    2195      265872 :                                         v = VALUE(r, canditer_peek(rci) - r->hseqbase);
    2196             :                         } else {
    2197        1182 :                                 if (rci->next == 0)
    2198             :                                         v = NULL; /* no more values */
    2199        1128 :                                 else if (mrci) {
    2200           0 :                                         oid rv = canditer_mask_next(mrci, canditer_peekprev(rci), false);
    2201           0 :                                         v = rv == oid_nil ? NULL : VALUE(r, rv - r->hseqbase);
    2202             :                                 } else
    2203        1128 :                                         v = VALUE(r, canditer_peekprev(rci) - r->hseqbase);
    2204             :                         }
    2205             :                         /* here, v points to next value in r, or if
    2206             :                          * we're at the end of r, v is NULL */
    2207       11206 :                         if (v == NULL) {
    2208        2371 :                                 nlx = lci->ncand - lci->next;
    2209             :                         } else {
    2210      267000 :                                 if (lscan < lci->ncand - lci->next) {
    2211      244764 :                                         lv = canditer_idx(lci, lci->next + lscan);
    2212      244764 :                                         lv -= l->hseqbase;
    2213      244764 :                                         if (lvals) {
    2214      238818 :                                                 if (lordering * cmp(VALUE(l, lv), v) < 0) {
    2215        2399 :                                                         nlx = binsearch(NULL, 0, li.type, lvals, lvars, li.width, lv, BATcount(l), v, lordering, 0);
    2216        2399 :                                                         nlx = canditer_search(lci, nlx + l->hseqbase, true);
    2217        2399 :                                                         nlx -= lci->next;
    2218             :                                                 }
    2219             :                                         } else {
    2220        5946 :                                                 assert(lordering == 1);
    2221        5946 :                                                 if (canditer_idx(&llci, lv) < *(const oid *)v) {
    2222           7 :                                                         nlx = canditer_search(&llci, *(const oid *)v, true);
    2223           7 :                                                         nlx = canditer_search(lci, nlx + l->hseqbase, true);
    2224           7 :                                                         nlx -= lci->next;
    2225             :                                                 }
    2226             :                                         }
    2227      244774 :                                         if (mlci) {
    2228           0 :                                                 lv = canditer_mask_next(mlci, lci->seq + lci->next + nlx, true);
    2229           0 :                                                 if (lv == oid_nil)
    2230           0 :                                                         nlx = lci->ncand - lci->next;
    2231             :                                                 else
    2232           0 :                                                         nlx = lv - lci->seq - lci->next;
    2233             :                                         }
    2234      244774 :                                         if (lci->next + nlx == lci->ncand)
    2235          12 :                                                 v = NULL;
    2236             :                                 }
    2237             :                         }
    2238      247145 :                         if (nlx > 0) {
    2239        4777 :                                 if (only_misses) {
    2240        2752 :                                         if (maybeextend(r1, r2, r3, nlx, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    2241           0 :                                                 goto bailout;
    2242      231667 :                                         while (nlx > 0) {
    2243      228915 :                                                 lv = canditer_next(lci);
    2244      228915 :                                                 if (mlci == NULL || canditer_contains(mlci, lv))
    2245      228914 :                                                         APPEND(r1, lv);
    2246      228915 :                                                 nlx--;
    2247             :                                         }
    2248        2752 :                                         if (r1->trevsorted && BATcount(r1) > 1)
    2249         647 :                                                 r1->trevsorted = false;
    2250        2025 :                                 } else if (nil_on_miss) {
    2251          19 :                                         if (r2 && r2->tnonil) {
    2252           2 :                                                 r2->tnil = true;
    2253           2 :                                                 r2->tnonil = false;
    2254           2 :                                                 r2->tseqbase = oid_nil;
    2255           2 :                                                 r2->tsorted = false;
    2256           2 :                                                 r2->trevsorted = false;
    2257           2 :                                                 r2->tkey = false;
    2258             :                                         }
    2259          19 :                                         if (maybeextend(r1, r2, r3, nlx, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    2260           0 :                                                 goto bailout;
    2261          19 :                                         if (r3)
    2262          18 :                                                 r3->tnil = false;
    2263        2072 :                                         while (nlx > 0) {
    2264        2053 :                                                 lv = canditer_next(lci);
    2265        2053 :                                                 if (mlci == NULL || canditer_contains(mlci, lv)) {
    2266        2053 :                                                         APPEND(r1, lv);
    2267        2053 :                                                         if (r2)
    2268           2 :                                                                 APPEND(r2, oid_nil);
    2269        2053 :                                                         if (r3) {
    2270        2052 :                                                                 if (rhasnil || cmp(VALUE(l, lv - l->hseqbase), nil) == 0) {
    2271           0 :                                                                         ((bit *) r3->theap->base)[r3->batCount++] = bit_nil;
    2272           0 :                                                                         r3->tnil = true;
    2273             :                                                                 } else {
    2274        2052 :                                                                         ((bit *) r3->theap->base)[r3->batCount++] = 0;
    2275             :                                                                 }
    2276             :                                                         }
    2277             :                                                 }
    2278        2053 :                                                 nlx--;
    2279             :                                         }
    2280          19 :                                         if (r1->trevsorted && BATcount(r1) > 1)
    2281           6 :                                                 r1->trevsorted = false;
    2282             :                                 } else {
    2283        2006 :                                         canditer_setidx(lci, lci->next + nlx);
    2284             :                                 }
    2285             :                         }
    2286      269381 :                         if (v == NULL) {
    2287             :                                 /* we have exhausted the inputs */
    2288             :                                 break;
    2289             :                         }
    2290             :                 }
    2291             : 
    2292             :                 /* Here we determine the next value in l that we are
    2293             :                  * going to try to match in r.  We will also count the
    2294             :                  * number of occurrences in l of that value.
    2295             :                  * Afterwards, v points to the value and nl is the
    2296             :                  * number of times it occurs.  Also, lci will point to
    2297             :                  * the next value to be considered (ready for the next
    2298             :                  * iteration).
    2299             :                  * If there are many equal values in l (more than
    2300             :                  * lscan), we will use binary search to find the end
    2301             :                  * of the sequence.  Obviously, we can do this only if
    2302             :                  * l is actually sorted (lscan > 0). */
    2303      567322 :                 nl = 1;         /* we'll match (at least) one in l */
    2304      567322 :                 nr = 0;         /* maybe we won't match anything in r */
    2305      567322 :                 lv = canditer_peek(lci);
    2306      567322 :                 if (mlci) {
    2307           0 :                         lv = canditer_mask_next(mlci, lv, true);
    2308           0 :                         if (lv == oid_nil)
    2309             :                                 break;
    2310           0 :                         canditer_setidx(lci, canditer_search(lci, lv, true));
    2311             :                 }
    2312      571676 :                 v = VALUE(l, lv - l->hseqbase);
    2313      571676 :                 if (li.key) {
    2314             :                         /* if l is key, there is a single value */
    2315      348792 :                 } else if (lscan > 0 &&
    2316      130064 :                            lscan < lci->ncand - lci->next &&
    2317       64366 :                            cmp(v, VALUE(l, canditer_idx(lci, lci->next + lscan) - l->hseqbase)) == 0) {
    2318             :                         /* lots of equal values: use binary search to
    2319             :                          * find end */
    2320        1389 :                         assert(lvals != NULL);
    2321        2773 :                         nl = binsearch(NULL, 0,
    2322        1389 :                                        li.type, lvals, lvars,
    2323        1389 :                                        li.width, lci->next + lscan,
    2324             :                                        BATcount(l),
    2325             :                                        v, lordering, 1);
    2326        1384 :                         nl = canditer_search(lci, nl + l->hseqbase, true);
    2327        1384 :                         nl -= lci->next;
    2328             :                 } else {
    2329      347192 :                         struct canditer ci = *lci; /* work on copy */
    2330      347192 :                         nl = 0; /* it will be incremented again */
    2331      551172 :                         do {
    2332      551172 :                                 canditer_next(&ci);
    2333      545151 :                                 nl++;
    2334     1085511 :                         } while (ci.next < ci.ncand &&
    2335      543067 :                                  cmp(v, VALUE(l, canditer_peek(&ci) - l->hseqbase)) == 0);
    2336             :                 }
    2337             :                 /* lci->next + nl is the position for the next iteration */
    2338             : 
    2339      562732 :                 if ((!nil_matches || not_in) && !li.nonil && cmp(v, nil) == 0) {
    2340         969 :                         if (not_in) {
    2341             :                                 /* just skip the whole thing: nils
    2342             :                                  * don't cause any output */
    2343           1 :                                 canditer_setidx(lci, lci->next + nl);
    2344           1 :                                 continue;
    2345             :                         }
    2346             :                         /* v is nil and nils don't match anything, set
    2347             :                          * to NULL to indicate nil */
    2348         968 :                         v = NULL;
    2349         968 :                         mark = bit_nil;
    2350         968 :                         if (r3)
    2351          54 :                                 r3->tnil = true;
    2352             :                 }
    2353             : 
    2354             :                 /* First we find the "first" value in r that is "at
    2355             :                  * least as large" as v, then we find the "first"
    2356             :                  * value in r that is "larger" than v.  The difference
    2357             :                  * is the number of values equal to v and is stored in
    2358             :                  * nr.  The definitions of "larger" and "first" depend
    2359             :                  * on the orderings of l and r.  If equal_order is
    2360             :                  * set, we go through r from low to high (this
    2361             :                  * includes the case that l is not sorted); otherwise
    2362             :                  * we go through r from high to low.
    2363             :                  * In either case, we will use binary search on r to
    2364             :                  * find both ends of the sequence of values that are
    2365             :                  * equal to v in case the position is "too far" (more
    2366             :                  * than rscan away). */
    2367          54 :                 if (v == NULL) {
    2368             :                         nr = 0; /* nils don't match anything */
    2369      560000 :                 } else if (ri.type == TYPE_void && is_oid_nil(r->tseqbase)) {
    2370           0 :                         if (is_oid_nil(*(const oid *) v)) {
    2371             :                                 /* all values in r match */
    2372           0 :                                 nr = rci->ncand;
    2373             :                         } else {
    2374             :                                 /* no value in r matches */
    2375             :                                 nr = 0;
    2376             :                         }
    2377             :                         /* in either case, we're done after this */
    2378           0 :                         canditer_setidx(rci, equal_order ? rci->ncand : 0);
    2379      560000 :                 } else if (equal_order) {
    2380             :                         /* first find the location of the first value
    2381             :                          * in r that is >= v, then find the location
    2382             :                          * of the first value in r that is > v; the
    2383             :                          * difference is the number of values equal
    2384             :                          * v; we change rci */
    2385             : 
    2386             :                         /* look ahead a little (rscan) in r to
    2387             :                          * see whether we're better off doing
    2388             :                          * a binary search */
    2389      558872 :                         if (rvals) {
    2390      547666 :                                 if (rscan < rci->ncand - rci->next &&
    2391      502434 :                                     rordering * cmp(v, VALUE(r, canditer_idx(rci, rci->next + rscan) - r->hseqbase)) > 0) {
    2392             :                                         /* value too far away in r:
    2393             :                                          * use binary search */
    2394      119925 :                                         lv = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, rci->next + rscan, BATcount(r), v, rordering, 0);
    2395      134090 :                                         lv = canditer_search(rci, lv + r->hseqbase, true);
    2396      134090 :                                         canditer_setidx(rci, lv);
    2397             :                                 } else {
    2398             :                                         /* scan r for v */
    2399      449474 :                                         while (rci->next < rci->ncand) {
    2400      448832 :                                                 if (rordering * cmp(v, VALUE(r, canditer_peek(rci) - r->hseqbase)) <= 0)
    2401             :                                                         break;
    2402       21114 :                                                 canditer_next(rci);
    2403             :                                         }
    2404             :                                 }
    2405     1084383 :                                 if (rci->next < rci->ncand &&
    2406      527607 :                                     cmp(v, VALUE(r, canditer_peek(rci) - r->hseqbase)) == 0) {
    2407             :                                         /* if we found an equal value,
    2408             :                                          * look for the last equal
    2409             :                                          * value */
    2410      309534 :                                         if (ri.key) {
    2411             :                                                 /* r is key, there can
    2412             :                                                  * only be a single
    2413             :                                                  * equal value */
    2414      160377 :                                                 nr = 1;
    2415      160377 :                                                 canditer_next(rci);
    2416      296189 :                                         } else if (rscan < rci->ncand - rci->next &&
    2417      147032 :                                                    cmp(v, VALUE(r, canditer_idx(rci, rci->next + rscan) - r->hseqbase)) == 0) {
    2418             :                                                 /* many equal values:
    2419             :                                                  * use binary search
    2420             :                                                  * to find the end */
    2421       66035 :                                                 nr = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, rci->next + rscan, BATcount(r), v, rordering, 1);
    2422       66035 :                                                 nr = canditer_search(rci, nr + r->hseqbase, true);
    2423       66035 :                                                 nr -= rci->next;
    2424       66035 :                                                 canditer_setidx(rci, rci->next + nr);
    2425             :                                         } else {
    2426             :                                                 /* scan r for end of
    2427             :                                                  * range */
    2428      228214 :                                                 do {
    2429      228214 :                                                         nr++;
    2430      228214 :                                                         canditer_next(rci);
    2431      455947 :                                                 } while (rci->next < rci->ncand &&
    2432      227734 :                                                          cmp(v, VALUE(r, canditer_peek(rci) - r->hseqbase)) == 0);
    2433             :                                         }
    2434             :                                 }
    2435             :                         } else {
    2436       11206 :                                 assert(rordering == 1);
    2437       11206 :                                 rval = canditer_search(&rrci, *(const oid*)v, true) + r->hseqbase;
    2438       11206 :                                 lv = canditer_search(rci, rval, true);
    2439       11206 :                                 canditer_setidx(rci, lv);
    2440       11206 :                                 nr = (canditer_idx(&rrci, canditer_peek(rci) - r->hseqbase) == *(oid*)v);
    2441       11206 :                                 if (nr == 1)
    2442       11206 :                                         canditer_next(rci);
    2443             :                         }
    2444             :                         /* rci points to first value > v or end of r,
    2445             :                          * and nr is the number of values in r that
    2446             :                          * are equal to v */
    2447             :                 } else {
    2448             :                         /* first find the location of the first value
    2449             :                          * in r that is > v, then find the location
    2450             :                          * of the first value in r that is >= v; the
    2451             :                          * difference is the number of values equal
    2452             :                          * v; we change rci */
    2453             : 
    2454             :                         /* look back from the end a little
    2455             :                          * (rscan) in r to see whether we're
    2456             :                          * better off doing a binary search */
    2457        1128 :                         if (rvals) {
    2458        1128 :                                 if (rci->next > rscan &&
    2459         627 :                                     rordering * cmp(v, VALUE(r, canditer_idx(rci, rci->next - rscan) - r->hseqbase)) < 0) {
    2460             :                                         /* value too far away
    2461             :                                          * in r: use binary
    2462             :                                          * search */
    2463          30 :                                         lv = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, 0, rci->next - rscan, v, rordering, 1);
    2464          30 :                                         lv = canditer_search(rci, lv + r->hseqbase, true);
    2465          30 :                                         canditer_setidx(rci, lv);
    2466             :                                 } else {
    2467             :                                         /* scan r for v */
    2468        2310 :                                         while (rci->next > 0 &&
    2469        2304 :                                                rordering * cmp(v, VALUE(r, canditer_peekprev(rci) - r->hseqbase)) < 0)
    2470        1214 :                                                 canditer_prev(rci);
    2471             :                                 }
    2472        2232 :                                 if (rci->next > 0 &&
    2473        1105 :                                     cmp(v, VALUE(r, canditer_peekprev(rci) - r->hseqbase)) == 0) {
    2474             :                                         /* if we found an equal value,
    2475             :                                          * look for the last equal
    2476             :                                          * value */
    2477        1014 :                                         if (ri.key) {
    2478             :                                                 /* r is key, there can only be a single equal value */
    2479         424 :                                                 nr = 1;
    2480         424 :                                                 canditer_prev(rci);
    2481        1080 :                                         } else if (rci->next > rscan &&
    2482         490 :                                                    cmp(v, VALUE(r, canditer_idx(rci, rci->next - rscan) - r->hseqbase)) == 0) {
    2483             :                                                 /* use binary search to find the start */
    2484          43 :                                                 nr = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, 0, rci->next - rscan, v, rordering, 0);
    2485          43 :                                                 nr = canditer_search(rci, nr + r->hseqbase, true);
    2486          43 :                                                 nr = rci->next - nr;
    2487          43 :                                                 canditer_setidx(rci, rci->next - nr);
    2488             :                                         } else {
    2489             :                                                 /* scan r for start of range */
    2490         653 :                                                 do {
    2491         653 :                                                         canditer_prev(rci);
    2492         653 :                                                         nr++;
    2493        1249 :                                                 } while (rci->next > 0 &&
    2494         596 :                                                          cmp(v, VALUE(r, canditer_peekprev(rci) - r->hseqbase)) == 0);
    2495             :                                         }
    2496             :                                 }
    2497             :                         } else {
    2498           0 :                                 lv = canditer_search(&rrci, *(const oid *)v, true);
    2499           0 :                                 lv = canditer_search(rci, lv + r->hseqbase, true);
    2500           0 :                                 nr = (canditer_idx(rci, lv) == *(const oid*)v);
    2501           0 :                                 canditer_setidx(rci, lv);
    2502             :                         }
    2503             :                         /* rci points to first value > v
    2504             :                          * or end of r, and nr is the number of values
    2505             :                          * in r that are equal to v */
    2506             :                 }
    2507             : 
    2508      325727 :                 if (nr == 0) {
    2509             :                         /* no entries in r found */
    2510      252255 :                         if (!(nil_on_miss | only_misses)) {
    2511      211182 :                                 if (min_one) {
    2512           0 :                                         GDKerror("not enough matches");
    2513           0 :                                         goto bailout;
    2514             :                                 }
    2515      215984 :                                 if (lscan > 0 &&
    2516        4802 :                                     (equal_order ? rci->next == rci->ncand : rci->next == 0)) {
    2517             :                                         /* nothing more left to match
    2518             :                                          * in r */
    2519             :                                         break;
    2520             :                                 }
    2521      211139 :                                 canditer_setidx(lci, lci->next + nl);
    2522      210573 :                                 continue;
    2523             :                         }
    2524             :                         /* insert a nil to indicate a non-match */
    2525       41073 :                         insert_nil = true;
    2526       41073 :                         nr = 1;
    2527       41073 :                         if (r2) {
    2528           4 :                                 r2->tnil = true;
    2529           4 :                                 r2->tnonil = false;
    2530           4 :                                 r2->tsorted = false;
    2531           4 :                                 r2->trevsorted = false;
    2532           4 :                                 r2->tseqbase = oid_nil;
    2533           4 :                                 r2->tkey = false;
    2534             :                         }
    2535      321569 :                 } else if (nr > 1 && max_one) {
    2536          21 :                         GDKerror("more than one match");
    2537          21 :                         goto bailout;
    2538      321548 :                 } else if (only_misses) {
    2539             :                         /* we had a match, so we're not interested */
    2540      142107 :                         canditer_setidx(lci, lci->next + nl);
    2541      142466 :                         continue;
    2542             :                 } else {
    2543      179441 :                         insert_nil = false;
    2544      179441 :                         if (semi) {
    2545             :                                 /* for semi-join, only insert single
    2546             :                                  * value */
    2547       35908 :                                 nr = 1;
    2548             :                         }
    2549             :                 }
    2550             :                 /* make space: nl values in l match nr values in r, so
    2551             :                  * we need to add nl * nr values in the results */
    2552      220514 :                 if (maybeextend(r1, r2, r3, nl * nr, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    2553           0 :                         goto bailout;
    2554             : 
    2555             :                 /* maintain properties */
    2556      220717 :                 if (nl > 1) {
    2557       64670 :                         if (r2) {
    2558             :                                 /* value occurs multiple times in l,
    2559             :                                  * so entry in r will be repeated
    2560             :                                  * multiple times: hence r2 is not key
    2561             :                                  * and not dense */
    2562       14848 :                                 r2->tkey = false;
    2563       14848 :                                 r2->tseqbase = oid_nil;
    2564             :                         }
    2565             :                         /* multiple different values will be inserted
    2566             :                          * in r1 (always in order), so not reverse
    2567             :                          * ordered anymore */
    2568       64670 :                         r1->trevsorted = false;
    2569             :                 }
    2570      220717 :                 if (nr > 1) {
    2571             :                         /* value occurs multiple times in r, so entry
    2572             :                          * in l will be repeated multiple times: hence
    2573             :                          * r1 is not key and not dense */
    2574       65857 :                         r1->tkey = false;
    2575       65857 :                         if (r2) {
    2576             :                                 /* multiple different values will be
    2577             :                                  * inserted in r2 (in order), so not
    2578             :                                  * reverse ordered anymore */
    2579       65429 :                                 r2->trevsorted = false;
    2580       65429 :                                 if (nl > 1) {
    2581             :                                         /* multiple values in l match
    2582             :                                          * multiple values in r, so an
    2583             :                                          * ordered sequence will be
    2584             :                                          * inserted multiple times in
    2585             :                                          * r2, so r2 is not ordered
    2586             :                                          * anymore */
    2587        7178 :                                         r2->tsorted = false;
    2588             :                                 }
    2589             :                         }
    2590             :                 }
    2591      220717 :                 if (lscan == 0) {
    2592             :                         /* deduce relative positions of r matches for
    2593             :                          * this and previous value in v */
    2594       87622 :                         if (prev && r2) {
    2595             :                                 /* keyness or r2 can only be assured
    2596             :                                  * as long as matched values are
    2597             :                                  * ordered */
    2598       86401 :                                 int ord = rordering * cmp(prev, v ? v : nil);
    2599       87135 :                                 if (ord < 0) {
    2600             :                                         /* previous value in l was
    2601             :                                          * less than current */
    2602       29356 :                                         r2->trevsorted = false;
    2603       29356 :                                         r2->tkey &= r2->tsorted;
    2604       57779 :                                 } else if (ord > 0) {
    2605             :                                         /* previous value was
    2606             :                                          * greater */
    2607       28466 :                                         r2->tsorted = false;
    2608       28466 :                                         r2->tkey &= r2->trevsorted;
    2609             :                                 } else {
    2610             :                                         /* value can be equal if
    2611             :                                          * intervening values in l
    2612             :                                          * didn't match anything; if
    2613             :                                          * multiple values match in r,
    2614             :                                          * r2 won't be sorted */
    2615       29313 :                                         r2->tkey = false;
    2616       29313 :                                         if (nr > 1) {
    2617       29271 :                                                 r2->tsorted = false;
    2618       29271 :                                                 r2->trevsorted = false;
    2619             :                                         }
    2620             :                                 }
    2621             :                         }
    2622       88356 :                         prev = v ? v : nil;
    2623             :                 }
    2624      221451 :                 if (BATcount(r1) > 0) {
    2625             :                         /* a new, higher value will be inserted into
    2626             :                          * r1, so r1 is not reverse ordered anymore */
    2627      216528 :                         r1->trevsorted = false;
    2628      216528 :                         if (r2) {
    2629             :                                 /* depending on whether l and r are
    2630             :                                  * ordered the same or not, a new
    2631             :                                  * higher or lower value will be added
    2632             :                                  * to r2 */
    2633       91742 :                                 if (equal_order)
    2634       91582 :                                         r2->trevsorted = false;
    2635             :                                 else {
    2636         160 :                                         r2->tsorted = false;
    2637         160 :                                         r2->tseqbase = oid_nil;
    2638             :                                 }
    2639             :                         }
    2640             :                 }
    2641             : 
    2642             :                 /* insert values: first the left output */
    2643             :                 BUN nladded = 0;
    2644      609125 :                 for (i = 0; i < nl; i++) {
    2645      388918 :                         lv = canditer_next(lci);
    2646      387674 :                         if (mlci == NULL || canditer_contains(mlci, lv)) {
    2647      386486 :                                 nladded++;
    2648    60571071 :                                 for (j = 0; j < nr; j++)
    2649    60184585 :                                         APPEND(r1, lv);
    2650             :                         }
    2651             :                 }
    2652      220207 :                 nl = nladded;
    2653             :                 /* then the right output, various different ways of
    2654             :                  * doing it */
    2655      220207 :                 if (r2) {
    2656       92126 :                         if (insert_nil) {
    2657          11 :                                 for (i = 0; i < nl; i++) {
    2658          14 :                                         for (j = 0; j < nr; j++) {
    2659           7 :                                                 APPEND(r2, oid_nil);
    2660             :                                         }
    2661             :                                 }
    2662       92122 :                         } else if (equal_order) {
    2663       91802 :                                 struct canditer ci = *rci; /* work on copy */
    2664       91802 :                                 if (r2->batCount > 0 &&
    2665       91261 :                                     BATtdense(r2) &&
    2666        5375 :                                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != canditer_idx(&ci, ci.next - nr))
    2667         104 :                                         r2->tseqbase = oid_nil;
    2668      216179 :                                 for (i = 0; i < nl; i++) {
    2669      124511 :                                         canditer_setidx(&ci, ci.next - nr);
    2670    60168980 :                                         for (j = 0; j < nr; j++) {
    2671    59920092 :                                                 APPEND(r2, canditer_next(&ci));
    2672             :                                         }
    2673             :                                 }
    2674             :                         } else {
    2675         320 :                                 if (r2->batCount > 0 &&
    2676         160 :                                     BATtdense(r2) &&
    2677           0 :                                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != canditer_peek(rci))
    2678           0 :                                         r2->tseqbase = oid_nil;
    2679        9284 :                                 for (i = 0; i < nl; i++) {
    2680        8965 :                                         struct canditer ci = *rci; /* work on copy */
    2681       18855 :                                         for (j = 0; j < nr; j++) {
    2682        9891 :                                                 APPEND(r2, canditer_next(&ci));
    2683             :                                         }
    2684             :                                 }
    2685             :                         }
    2686             :                 }
    2687             :                 /* finally the mark output */
    2688      220072 :                 if (r3) {
    2689        2490 :                         if (insert_nil) {
    2690         332 :                                 r3->tnil |= rhasnil;
    2691         831 :                                 for (i = 0; i < nl; i++) {
    2692         998 :                                         for (j = 0; j < nr; j++) {
    2693         499 :                                                 ((bit *) r3->theap->base)[r3->batCount++] = mark;
    2694             :                                         }
    2695             :                                 }
    2696             :                         } else {
    2697        7539 :                                 for (i = 0; i < nl; i++) {
    2698       10766 :                                         for (j = 0; j < nr; j++) {
    2699        5385 :                                                 ((bit *) r3->theap->base)[r3->batCount++] = 1;
    2700             :                                         }
    2701             :                                 }
    2702             :                         }
    2703             :                 }
    2704             :         }
    2705             :         /* also set other bits of heap to correct value to indicate size */
    2706        8046 :         BATsetcount(r1, BATcount(r1));
    2707        8041 :         r1->tseqbase = oid_nil;
    2708        8041 :         if (r1->tkey)
    2709        7944 :                 r1 = virtualize(r1);
    2710        7963 :         if (r2) {
    2711        2392 :                 BATsetcount(r2, BATcount(r2));
    2712        2398 :                 assert(BATcount(r1) == BATcount(r2));
    2713        2398 :                 r2->tseqbase = oid_nil;
    2714        2398 :                 if (BATcount(r2) <= 1) {
    2715        1485 :                         r2->tkey = true;
    2716        1485 :                         r2 = virtualize(r2);
    2717             :                 }
    2718             :         }
    2719        7988 :         if (r3) {
    2720          68 :                 BATsetcount(r3, BATcount(r3));
    2721          68 :                 assert(BATcount(r1) == BATcount(r3));
    2722          68 :                 r3->tseqbase = oid_nil;
    2723          68 :                 r3->tnonil = !r3->tnil;
    2724          68 :                 if (BATcount(r3) <= 1) {
    2725           0 :                         r3->tkey = true;
    2726           0 :                         r3->tsorted = true;
    2727           0 :                         r3->trevsorted = true;
    2728             :                 }
    2729             :         }
    2730        7988 :         bat_iterator_end(&li);
    2731        8056 :         bat_iterator_end(&ri);
    2732        8019 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
    2733             :                   "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    2734             :                   "sr=" ALGOOPTBATFMT ","
    2735             :                   "nil_on_miss=%s,semi=%s,only_misses=%s,not_in=%s;%s %s "
    2736             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT " (" LLFMT "usec)\n",
    2737             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    2738             :                   ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    2739             :                   nil_on_miss ? "true" : "false",
    2740             :                   semi ? "true" : "false",
    2741             :                   only_misses ? "true" : "false",
    2742             :                   not_in ? "true" : "false",
    2743             :                   swapped ? " swapped" : "", reason,
    2744             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    2745             :                   GDKusec() - t0);
    2746             : 
    2747             :         return GDK_SUCCEED;
    2748             : 
    2749          21 :   bailout:
    2750          21 :         bat_iterator_end(&li);
    2751          21 :         bat_iterator_end(&ri);
    2752          21 :         BBPreclaim(r1);
    2753          21 :         BBPreclaim(r2);
    2754          21 :         BBPreclaim(r3);
    2755             :         return GDK_FAIL;
    2756             : }
    2757             : 
    2758             : #define HASHLOOPBODY()                                                  \
    2759             :         do {                                                            \
    2760             :                 if (nr >= 1 && max_one) {                            \
    2761             :                         GDKerror("more than one match");              \
    2762             :                         goto bailout;                                   \
    2763             :                 }                                                       \
    2764             :                 if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED) \
    2765             :                         goto bailout;                                   \
    2766             :                 APPEND(r1, lo);                                         \
    2767             :                 if (r2)                                                 \
    2768             :                         APPEND(r2, ro);                                 \
    2769             :                 if (r3)                                                 \
    2770             :                         ((bit *) r3->theap->base)[r3->batCount++] = 1; \
    2771             :                 nr++;                                                   \
    2772             :         } while (false)
    2773             : 
    2774             : #define EQ_int(a, b)    ((a) == (b))
    2775             : #define EQ_lng(a, b)    ((a) == (b))
    2776             : #ifdef HAVE_HGE
    2777             : #define EQ_uuid(a, b)   ((a).h == (b).h)
    2778             : #else
    2779             : #define EQ_uuid(a, b)   (memcmp((a).u, (b).u, UUID_SIZE) == 0)
    2780             : #endif
    2781             : 
    2782             : #define HASHJOIN(TYPE)                                                  \
    2783             :         do {                                                            \
    2784             :                 TYPE *rvals = ri.base;                                  \
    2785             :                 TYPE *lvals = li.base;                                  \
    2786             :                 TYPE v;                                                 \
    2787             :                 while (lci->next < lci->ncand) {                       \
    2788             :                         GDK_CHECK_TIMEOUT(qry_ctx, counter, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
    2789             :                         lo = canditer_next(lci);                        \
    2790             :                         v = lvals[lo - l->hseqbase];                 \
    2791             :                         nr = 0;                                         \
    2792             :                         bit mark = defmark;                             \
    2793             :                         if ((!nil_matches || not_in) && is_##TYPE##_nil(v)) { \
    2794             :                                 /* no match */                          \
    2795             :                                 if (not_in) {                           \
    2796             :                                         lskipped = BATcount(r1) > 0; \
    2797             :                                         continue;                       \
    2798             :                                 }                                       \
    2799             :                                 mark = bit_nil;                         \
    2800             :                         } else if (hash_cand) {                         \
    2801             :                                 /* private hash: no locks */            \
    2802             :                                 for (rb = HASHget(hsh, hash_##TYPE(hsh, &v)); \
    2803             :                                      rb != BUN_NONE;                    \
    2804             :                                      rb = HASHgetlink(hsh, rb)) {       \
    2805             :                                         ro = canditer_idx(rci, rb);     \
    2806             :                                         if (!EQ_##TYPE(v, rvals[ro - r->hseqbase])) \
    2807             :                                                 continue;               \
    2808             :                                         if (only_misses) {              \
    2809             :                                                 nr++;                   \
    2810             :                                                 break;                  \
    2811             :                                         }                               \
    2812             :                                         HASHLOOPBODY();                 \
    2813             :                                         if (semi && !max_one)           \
    2814             :                                                 break;                  \
    2815             :                                 }                                       \
    2816             :                         } else if (rci->tpe != cand_dense) {         \
    2817             :                                 for (rb = HASHget(hsh, hash_##TYPE(hsh, &v)); \
    2818             :                                      rb != BUN_NONE;                    \
    2819             :                                      rb = HASHgetlink(hsh, rb)) {       \
    2820             :                                         if (rb >= rl && rb < rh &&        \
    2821             :                                             EQ_##TYPE(v, rvals[rb]) &&  \
    2822             :                                             canditer_contains(rci, ro = (oid) (rb - roff + rseq))) { \
    2823             :                                                 if (only_misses) {      \
    2824             :                                                         nr++;           \
    2825             :                                                         break;          \
    2826             :                                                 }                       \
    2827             :                                                 HASHLOOPBODY();         \
    2828             :                                                 if (semi && !max_one)   \
    2829             :                                                         break;          \
    2830             :                                         }                               \
    2831             :                                 }                                       \
    2832             :                         } else {                                        \
    2833             :                                 for (rb = HASHget(hsh, hash_##TYPE(hsh, &v)); \
    2834             :                                      rb != BUN_NONE;                    \
    2835             :                                      rb = HASHgetlink(hsh, rb)) {       \
    2836             :                                         if (rb >= rl && rb < rh &&        \
    2837             :                                             EQ_##TYPE(v, rvals[rb])) {  \
    2838             :                                                 if (only_misses) {      \
    2839             :                                                         nr++;           \
    2840             :                                                         break;          \
    2841             :                                                 }                       \
    2842             :                                                 ro = (oid) (rb - roff + rseq); \
    2843             :                                                 HASHLOOPBODY();         \
    2844             :                                                 if (semi && !max_one)   \
    2845             :                                                         break;          \
    2846             :                                         }                               \
    2847             :                                 }                                       \
    2848             :                         }                                               \
    2849             :                         if (nr == 0) {                                  \
    2850             :                                 if (only_misses) {                      \
    2851             :                                         nr = 1;                         \
    2852             :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED) \
    2853             :                                                 goto bailout;           \
    2854             :                                         APPEND(r1, lo);                 \
    2855             :                                         if (lskipped)                   \
    2856             :                                                 r1->tseqbase = oid_nil;      \
    2857             :                                 } else if (nil_on_miss) {               \
    2858             :                                         nr = 1;                         \
    2859             :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED) \
    2860             :                                                 goto bailout;           \
    2861             :                                         APPEND(r1, lo);                 \
    2862             :                                         if (r2) {                       \
    2863             :                                                 r2->tnil = true;     \
    2864             :                                                 r2->tnonil = false;  \
    2865             :                                                 r2->tkey = false;    \
    2866             :                                                 APPEND(r2, oid_nil);    \
    2867             :                                         }                               \
    2868             :                                         if (r3) {                       \
    2869             :                                                 r3->tnil |= mark == bit_nil; \
    2870             :                                                 ((bit *) r3->theap->base)[r3->batCount++] = mark; \
    2871             :                                         }                               \
    2872             :                                 } else if (min_one) {                   \
    2873             :                                         GDKerror("not enough matches");       \
    2874             :                                         goto bailout;                   \
    2875             :                                 } else {                                \
    2876             :                                         lskipped = BATcount(r1) > 0; \
    2877             :                                 }                                       \
    2878             :                         } else if (only_misses) {                       \
    2879             :                                 lskipped = BATcount(r1) > 0;         \
    2880             :                         } else {                                        \
    2881             :                                 if (lskipped) {                         \
    2882             :                                         /* note, we only get here in an \
    2883             :                                          * iteration *after* lskipped was \
    2884             :                                          * first set to true, i.e. we did \
    2885             :                                          * indeed skip values in l */   \
    2886             :                                         r1->tseqbase = oid_nil;              \
    2887             :                                 }                                       \
    2888             :                                 if (nr > 1) {                                \
    2889             :                                         r1->tkey = false;            \
    2890             :                                         r1->tseqbase = oid_nil;              \
    2891             :                                 }                                       \
    2892             :                         }                                               \
    2893             :                         if (nr > 0 && BATcount(r1) > nr)          \
    2894             :                                 r1->trevsorted = false;                      \
    2895             :                 }                                                       \
    2896             :         } while (0)
    2897             : 
    2898             : /* Implementation of join using a hash lookup of values in the right
    2899             :  * column. */
    2900             : static gdk_return
    2901       17513 : hashjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
    2902             :          struct canditer *restrict lci, struct canditer *restrict rci,
    2903             :          bool nil_matches, bool nil_on_miss, bool semi, bool only_misses,
    2904             :          bool not_in, bool max_one, bool min_one,
    2905             :          BUN estimate, lng t0, bool swapped,
    2906             :          bool hash, bool phash, bool hash_cand,
    2907             :          const char *reason)
    2908             : {
    2909       17513 :         oid lo, ro;
    2910       17513 :         BATiter li, ri;
    2911       17513 :         BUN rb, roff = 0;
    2912             :         /* rl, rh: lower and higher bounds for BUN values in hash table */
    2913       17513 :         BUN rl, rh;
    2914       17513 :         oid rseq;
    2915       17513 :         BUN nr;
    2916       17513 :         const char *lvals;
    2917       17513 :         const char *lvars;
    2918       17513 :         const void *nil = ATOMnilptr(l->ttype);
    2919       17513 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    2920       17513 :         oid lval = oid_nil;     /* hold value if l is dense */
    2921       17513 :         const char *v = (const char *) &lval;
    2922       17513 :         bool lskipped = false;  /* whether we skipped values in l */
    2923       17513 :         Hash *restrict hsh = NULL;
    2924       17513 :         bool locked = false;
    2925       17513 :         BUN maxsize;
    2926       17513 :         BAT *r1 = NULL;
    2927       17513 :         BAT *r2 = NULL;
    2928       17513 :         BAT *r3 = NULL;
    2929       17513 :         BAT *b = NULL;
    2930             : 
    2931       52497 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    2932             : 
    2933       17513 :         size_t counter = 0;
    2934       17513 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2935             : 
    2936       17511 :         li = bat_iterator(l);
    2937       17519 :         ri = bat_iterator(r);
    2938             : 
    2939       17510 :         int t = ATOMbasetype(ri.type);
    2940       17510 :         if (BATtvoid(r) || BATtvoid(l))
    2941           0 :                 t = TYPE_void;
    2942             : 
    2943       17510 :         lvals = (const char *) li.base;
    2944       17510 :         if (li.vh && li.type) {
    2945        1140 :                 assert(ri.vh && ri.type);
    2946        1140 :                 lvars = li.vh->base;
    2947             :         } else {
    2948       16370 :                 assert(ri.vh == NULL);
    2949             :                 lvars = NULL;
    2950             :         }
    2951             :         /* offset to convert BUN to OID for value in right column */
    2952       17510 :         rseq = r->hseqbase;
    2953             : 
    2954       17510 :         rl = rci->seq - r->hseqbase;
    2955       17510 :         rh = canditer_last(rci) + 1 - r->hseqbase;
    2956       17510 :         if (hash_cand) {
    2957             :                 /* we need to create a hash on r specific for the
    2958             :                  * candidate list */
    2959         180 :                 char ext[32];
    2960         180 :                 assert(rci->s);
    2961         228 :                 MT_thread_setalgorithm(swapped ? "hashjoin using candidate hash (swapped)" : "hashjoin using candidate hash");
    2962         180 :                 TRC_DEBUG(ALGO, ALGOBATFMT ": creating "
    2963             :                           "hash for candidate list " ALGOBATFMT "%s%s\n",
    2964             :                           ALGOBATPAR(r), ALGOBATPAR(rci->s),
    2965             :                           r->thash ? " ignoring existing hash" : "",
    2966             :                           swapped ? " (swapped)" : "");
    2967         180 :                 if (snprintf(ext, sizeof(ext), "thshjn%x",
    2968         180 :                              (unsigned) MT_getpid()) >= (int) sizeof(ext))
    2969           0 :                         goto bailout;
    2970         180 :                 if ((hsh = BAThash_impl(r, rci, ext)) == NULL) {
    2971           0 :                         goto bailout;
    2972             :                 }
    2973       17330 :         } else if (phash) {
    2974             :                 /* there is a hash on the parent which we should use */
    2975        1921 :                 MT_thread_setalgorithm(swapped ? "hashjoin using parent hash (swapped)" : "hashjoin using parent hash");
    2976        1674 :                 b = BATdescriptor(VIEWtparent(r));
    2977        1674 :                 if (b == NULL)
    2978           0 :                         goto bailout;
    2979        1674 :                 TRC_DEBUG(ALGO, "%s(%s): using "
    2980             :                           "parent(" ALGOBATFMT ") for hash%s\n",
    2981             :                           __func__,
    2982             :                           BATgetId(r), ALGOBATPAR(b),
    2983             :                           swapped ? " (swapped)" : "");
    2984        1674 :                 roff = r->tbaseoff - b->tbaseoff;
    2985        1674 :                 rl += roff;
    2986        1674 :                 rh += roff;
    2987        1674 :                 r = b;
    2988        1674 :                 bat_iterator_end(&ri);
    2989        1674 :                 ri = bat_iterator(r);
    2990        1674 :                 MT_rwlock_rdlock(&r->thashlock);
    2991        1674 :                 hsh = r->thash;
    2992        1674 :                 locked = true;
    2993       15656 :         } else if (hash) {
    2994             :                 /* there is a hash on r which we should use */
    2995       13491 :                 MT_thread_setalgorithm(swapped ? "hashjoin using existing hash (swapped)" : "hashjoin using existing hash");
    2996        7823 :                 MT_rwlock_rdlock(&r->thashlock);
    2997        7826 :                 hsh = r->thash;
    2998        7826 :                 locked = true;
    2999        7826 :                 TRC_DEBUG(ALGO, ALGOBATFMT ": using "
    3000             :                           "existing hash%s\n",
    3001             :                           ALGOBATPAR(r),
    3002             :                           swapped ? " (swapped)" : "");
    3003        7832 :         } else if (BATtdensebi(&ri)) {
    3004             :                 /* no hash, just dense lookup */
    3005           0 :                 MT_thread_setalgorithm(swapped ? "hashjoin on dense (swapped)" : "hashjoin on dense");
    3006             :         } else {
    3007             :                 /* we need to create a hash on r */
    3008       10928 :                 MT_thread_setalgorithm(swapped ? "hashjoin using new hash (swapped)" : "hashjoin using new hash");
    3009        7839 :                 TRC_DEBUG(ALGO, ALGOBATFMT ": creating hash%s\n",
    3010             :                           ALGOBATPAR(r),
    3011             :                           swapped ? " (swapped)" : "");
    3012        7839 :                 if (BAThash(r) != GDK_SUCCEED)
    3013           0 :                         goto bailout;
    3014        7794 :                 MT_rwlock_rdlock(&r->thashlock);
    3015        7839 :                 hsh = r->thash;
    3016        7839 :                 locked = true;
    3017             :         }
    3018       17519 :         if (locked && hsh == NULL) {
    3019           0 :                 GDKerror("Hash disappeared for "ALGOBATFMT"\n", ALGOBATPAR(r));
    3020           0 :                 goto bailout;
    3021             :         }
    3022       17519 :         assert(hsh != NULL || BATtdensebi(&ri));
    3023             :         if (hsh) {
    3024       17519 :                 TRC_DEBUG(ALGO, "hash for " ALGOBATFMT ": nbucket " BUNFMT ", nunique " BUNFMT ", nheads " BUNFMT "\n", ALGOBATPAR(r), hsh->nbucket, hsh->nunique, hsh->nheads);
    3025             :         }
    3026             : 
    3027       17519 :         bit defmark = 0;
    3028       17519 :         if ((not_in || r3p) && !ri.nonil) {
    3029             :                 /* check whether there is a nil on the right, since if
    3030             :                  * so, we should return an empty result if not_in is
    3031             :                  * set, or use a NIL mark for non-matches if r3p is
    3032             :                  * set */
    3033         477 :                 if (hash_cand) {
    3034           0 :                         for (rb = HASHget(hsh, HASHprobe(hsh, nil));
    3035           0 :                              rb != BUN_NONE;
    3036           0 :                              rb = HASHgetlink(hsh, rb)) {
    3037           0 :                                 ro = canditer_idx(rci, rb);
    3038           0 :                                 if ((*cmp)(nil, BUNtail(ri, ro - r->hseqbase)) == 0) {
    3039           0 :                                         assert(!locked);
    3040           0 :                                         if (r3p) {
    3041           0 :                                                 defmark = bit_nil;
    3042           0 :                                                 break;
    3043             :                                         }
    3044           0 :                                         HEAPfree(&hsh->heaplink, true);
    3045           0 :                                         HEAPfree(&hsh->heapbckt, true);
    3046           0 :                                         GDKfree(hsh);
    3047           0 :                                         bat_iterator_end(&li);
    3048           0 :                                         bat_iterator_end(&ri);
    3049           0 :                                         BBPreclaim(b);
    3050           0 :                                         return nomatch(r1p, r2p, r3p, l, r, lci,
    3051             :                                                        bit_nil, false, false,
    3052             :                                                        __func__, t0);
    3053             :                                 }
    3054             :                         }
    3055         477 :                 } else if (!BATtdensebi(&ri)) {
    3056         477 :                         for (rb = HASHget(hsh, HASHprobe(hsh, nil));
    3057        5074 :                              rb != BUN_NONE;
    3058        4598 :                              rb = HASHgetlink(hsh, rb)) {
    3059        4626 :                                 if (rb >= rl && rb < rh &&
    3060        4626 :                                     (cmp == NULL ||
    3061        4626 :                                      (*cmp)(nil, BUNtail(ri, rb)) == 0)) {
    3062          28 :                                         if (r3p) {
    3063          27 :                                                 defmark = bit_nil;
    3064          27 :                                                 break;
    3065             :                                         }
    3066           1 :                                         if (locked)
    3067           1 :                                                 MT_rwlock_rdunlock(&r->thashlock);
    3068           1 :                                         bat_iterator_end(&li);
    3069           1 :                                         bat_iterator_end(&ri);
    3070           1 :                                         BBPreclaim(b);
    3071           1 :                                         return nomatch(r1p, r2p, r3p, l, r, lci,
    3072             :                                                        bit_nil, false, false,
    3073             :                                                        __func__, t0);
    3074             :                                 }
    3075             :                         }
    3076             :                 }
    3077             :         }
    3078             : 
    3079       34957 :         maxsize = joininitresults(r1p, r2p, r3p, lci->ncand, rci->ncand,
    3080       17517 :                                   li.key, ri.key, semi | max_one,
    3081             :                                   nil_on_miss, only_misses, min_one,
    3082             :                                   estimate);
    3083       17440 :         if (maxsize == BUN_NONE) {
    3084           0 :                 goto bailout;
    3085             :         }
    3086             : 
    3087       17440 :         r1 = *r1p;
    3088       17440 :         r2 = r2p ? *r2p : NULL;
    3089       17440 :         r3 = r3p ? *r3p : NULL;
    3090             : 
    3091             :         /* basic properties will be adjusted if necessary later on,
    3092             :          * they were initially set by joininitresults() */
    3093             : 
    3094       17440 :         if (r2) {
    3095       14005 :                 r2->tkey = li.key;
    3096             :                 /* r2 is not likely to be sorted (although it is
    3097             :                  * certainly possible) */
    3098       14005 :                 r2->tsorted = false;
    3099       14005 :                 r2->trevsorted = false;
    3100       14005 :                 r2->tseqbase = oid_nil;
    3101             :         }
    3102             : 
    3103       17440 :         if (lci->tpe != cand_dense)
    3104         406 :                 r1->tseqbase = oid_nil;
    3105             : 
    3106             : 
    3107       17440 :         switch (t) {
    3108       14067 :         case TYPE_int:
    3109   347104686 :                 HASHJOIN(int);
    3110             :                 break;
    3111        1490 :         case TYPE_lng:
    3112   108676414 :                 HASHJOIN(lng);
    3113             :                 break;
    3114           0 :         case TYPE_uuid:
    3115           0 :                 HASHJOIN(uuid);
    3116           0 :                 break;
    3117             :         default:
    3118     2456506 :                 while (lci->next < lci->ncand) {
    3119     2454628 :                         GDK_CHECK_TIMEOUT(qry_ctx, counter,
    3120             :                                         GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    3121     2454628 :                         lo = canditer_next(lci);
    3122     2480131 :                         if (BATtdensebi(&li))
    3123         323 :                                 lval = lo - l->hseqbase + l->tseqbase;
    3124     2479808 :                         else if (li.type != TYPE_void)
    3125     2490409 :                                 v = VALUE(l, lo - l->hseqbase);
    3126     2480131 :                         nr = 0;
    3127     2480131 :                         bit mark = defmark;
    3128     2480131 :                         if ((!nil_matches || not_in) && cmp(v, nil) == 0) {
    3129             :                                 /* no match */
    3130        2973 :                                 if (not_in) {
    3131          10 :                                         lskipped = BATcount(r1) > 0;
    3132          10 :                                         continue;
    3133             :                                 }
    3134        2963 :                                 mark = bit_nil;
    3135     2479619 :                         } else if (hash_cand) {
    3136           0 :                                 for (rb = HASHget(hsh, HASHprobe(hsh, v));
    3137           0 :                                      rb != BUN_NONE;
    3138           0 :                                      rb = HASHgetlink(hsh, rb)) {
    3139           0 :                                         ro = canditer_idx(rci, rb);
    3140           0 :                                         if ((*cmp)(v, BUNtail(ri, ro - r->hseqbase)) != 0)
    3141           0 :                                                 continue;
    3142           0 :                                         if (only_misses) {
    3143           0 :                                                 nr++;
    3144           0 :                                                 break;
    3145             :                                         }
    3146           0 :                                         HASHLOOPBODY();
    3147           0 :                                         if (semi && !max_one)
    3148             :                                                 break;
    3149             :                                 }
    3150     2479619 :                         } else if (hsh == NULL) {
    3151           0 :                                 assert(BATtdensebi(&ri));
    3152           0 :                                 ro = *(const oid *) v;
    3153           0 :                                 if (ro >= r->tseqbase &&
    3154           0 :                                     ro < r->tseqbase + r->batCount) {
    3155           0 :                                         ro -= r->tseqbase;
    3156           0 :                                         ro += rseq;
    3157           0 :                                         if (canditer_contains(rci, ro)) {
    3158           0 :                                                 if (only_misses) {
    3159       17464 :                                                         nr++;
    3160             :                                                         break;
    3161             :                                                 }
    3162           0 :                                                 HASHLOOPBODY();
    3163           0 :                                                 if (semi && !max_one)
    3164             :                                                         break;
    3165             :                                         }
    3166             :                                 }
    3167     2479619 :                         } else if (rci->tpe != cand_dense) {
    3168           0 :                                 for (rb = HASHget(hsh, HASHprobe(hsh, v));
    3169           0 :                                      rb != BUN_NONE;
    3170           0 :                                      rb = HASHgetlink(hsh, rb)) {
    3171           0 :                                         if (rb >= rl && rb < rh &&
    3172           0 :                                             (*(cmp))(v, BUNtail(ri, rb)) == 0 &&
    3173           0 :                                             canditer_contains(rci, ro = (oid) (rb - roff + rseq))) {
    3174           0 :                                                 if (only_misses) {
    3175           0 :                                                         nr++;
    3176           0 :                                                         break;
    3177             :                                                 }
    3178           0 :                                                 HASHLOOPBODY();
    3179           0 :                                                 if (semi && !max_one)
    3180             :                                                         break;
    3181             :                                         }
    3182             :                                 }
    3183             :                         } else {
    3184     2479619 :                                 for (rb = HASHget(hsh, HASHprobe(hsh, v));
    3185     4875453 :                                      rb != BUN_NONE;
    3186     2338882 :                                      rb = HASHgetlink(hsh, rb)) {
    3187     4980450 :                                         if (rb >= rl && rb < rh &&
    3188     2550190 :                                             (*(cmp))(v, BUNtail(ri, rb)) == 0) {
    3189     2086401 :                                                 if (only_misses) {
    3190       50302 :                                                         nr++;
    3191       50302 :                                                         break;
    3192             :                                                 }
    3193     2036099 :                                                 ro = (oid) (rb - roff + rseq);
    3194     2036099 :                                                 HASHLOOPBODY();
    3195     1995636 :                                                 if (semi && !max_one)
    3196             :                                                         break;
    3197             :                                         }
    3198             :                                 }
    3199             :                         }
    3200     2454451 :                         if (nr == 0) {
    3201      386389 :                                 if (only_misses) {
    3202         259 :                                         nr = 1;
    3203         259 :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    3204           0 :                                                 goto bailout;
    3205         259 :                                         APPEND(r1, lo);
    3206         259 :                                         if (lskipped)
    3207         231 :                                                 r1->tseqbase = oid_nil;
    3208      386130 :                                 } else if (nil_on_miss) {
    3209       12917 :                                         nr = 1;
    3210       12917 :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    3211           0 :                                                 goto bailout;
    3212       13079 :                                         APPEND(r1, lo);
    3213       13079 :                                         if (r2) {
    3214           0 :                                                 r2->tnil = true;
    3215           0 :                                                 r2->tnonil = false;
    3216           0 :                                                 r2->tkey = false;
    3217           0 :                                                 APPEND(r2, oid_nil);
    3218             :                                         }
    3219       13079 :                                         if (r3) {
    3220       13079 :                                                 r3->tnil |= mark == bit_nil;
    3221       13079 :                                                 ((bit *) r3->theap->base)[r3->batCount++] = mark;
    3222             :                                         }
    3223      373213 :                                 } else if (min_one) {
    3224           0 :                                         GDKerror("not enough matches");
    3225           0 :                                         goto bailout;
    3226             :                                 } else {
    3227      373213 :                                         lskipped = BATcount(r1) > 0;
    3228             :                                 }
    3229     2068062 :                         } else if (only_misses) {
    3230       50249 :                                 lskipped = BATcount(r1) > 0;
    3231             :                         } else {
    3232     2017813 :                                 if (lskipped) {
    3233             :                                         /* note, we only get here in an
    3234             :                                          * iteration *after* lskipped was
    3235             :                                          * first set to true, i.e. we did
    3236             :                                          * indeed skip values in l */
    3237     1867847 :                                         r1->tseqbase = oid_nil;
    3238             :                                 }
    3239     2017813 :                                 if (nr > 1) {
    3240        2491 :                                         r1->tkey = false;
    3241        2491 :                                         r1->tseqbase = oid_nil;
    3242             :                                 }
    3243             :                         }
    3244     2454613 :                         if (nr > 0 && BATcount(r1) > nr)
    3245     2094834 :                                 r1->trevsorted = false;
    3246             :                 }
    3247             :                 break;
    3248             :         }
    3249       17464 :         if (locked) {
    3250       17274 :                 locked = false;
    3251       17274 :                 MT_rwlock_rdunlock(&r->thashlock);
    3252             :         }
    3253       17519 :         bat_iterator_end(&li);
    3254       17508 :         bat_iterator_end(&ri);
    3255             : 
    3256       17508 :         if (hash_cand) {
    3257         180 :                 HEAPfree(&hsh->heaplink, true);
    3258         180 :                 HEAPfree(&hsh->heapbckt, true);
    3259         180 :                 GDKfree(hsh);
    3260             :         }
    3261             :         /* also set other bits of heap to correct value to indicate size */
    3262       17508 :         BATsetcount(r1, BATcount(r1));
    3263       17451 :         r1->tunique_est = MIN(l->tunique_est, r->tunique_est);
    3264       17451 :         if (BATcount(r1) <= 1) {
    3265        6428 :                 r1->tsorted = true;
    3266        6428 :                 r1->trevsorted = true;
    3267        6428 :                 r1->tkey = true;
    3268        6428 :                 r1->tseqbase = 0;
    3269             :         }
    3270       17451 :         if (r2) {
    3271       14041 :                 BATsetcount(r2, BATcount(r2));
    3272       14050 :                 assert(BATcount(r1) == BATcount(r2));
    3273       14050 :                 if (BATcount(r2) <= 1) {
    3274        5234 :                         r2->tsorted = true;
    3275        5234 :                         r2->trevsorted = true;
    3276        5234 :                         r2->tkey = true;
    3277        5234 :                         r2->tseqbase = 0;
    3278             :                 }
    3279       20958 :                 r2->tunique_est = MIN(l->tunique_est, r->tunique_est);
    3280             :         }
    3281       17460 :         if (r3) {
    3282          49 :                 r3->tnonil = !r3->tnil;
    3283          49 :                 BATsetcount(r3, BATcount(r3));
    3284          49 :                 assert(BATcount(r1) == BATcount(r3));
    3285          86 :                 r3->tunique_est = MIN(l->tunique_est, r->tunique_est);
    3286             :         }
    3287       17460 :         if (BATcount(r1) > 0) {
    3288       12355 :                 if (BATtdense(r1))
    3289        6365 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    3290       12355 :                 if (r2 && BATtdense(r2))
    3291        1242 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    3292             :         } else {
    3293        5105 :                 r1->tseqbase = 0;
    3294        5105 :                 if (r2) {
    3295        3970 :                         r2->tseqbase = 0;
    3296             :                 }
    3297             :         }
    3298       17460 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT
    3299             :                   ",sl=" ALGOOPTBATFMT "," "sr=" ALGOOPTBATFMT ","
    3300             :                   "nil_matches=%s,nil_on_miss=%s,semi=%s,only_misses=%s,"
    3301             :                   "not_in=%s,max_one=%s,min_one=%s;%s %s -> " ALGOBATFMT "," ALGOOPTBATFMT
    3302             :                   " (" LLFMT "usec)\n",
    3303             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    3304             :                   ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    3305             :                   nil_matches ? "true" : "false",
    3306             :                   nil_on_miss ? "true" : "false",
    3307             :                   semi ? "true" : "false",
    3308             :                   only_misses ? "true" : "false",
    3309             :                   not_in ? "true" : "false",
    3310             :                   max_one ? "true" : "false",
    3311             :                   min_one ? "true" : "false",
    3312             :                   swapped ? " swapped" : "", reason,
    3313             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    3314             :                   GDKusec() - t0);
    3315             : 
    3316       17460 :         BBPreclaim(b);
    3317             :         return GDK_SUCCEED;
    3318             : 
    3319           6 :   bailout:
    3320           6 :         bat_iterator_end(&li);
    3321           6 :         bat_iterator_end(&ri);
    3322           6 :         if (locked)
    3323           6 :                 MT_rwlock_rdunlock(&r->thashlock);
    3324           6 :         if (hash_cand && hsh) {
    3325           0 :                 HEAPfree(&hsh->heaplink, true);
    3326           0 :                 HEAPfree(&hsh->heapbckt, true);
    3327           0 :                 GDKfree(hsh);
    3328             :         }
    3329           6 :         BBPreclaim(r1);
    3330           6 :         BBPreclaim(r2);
    3331           6 :         BBPreclaim(b);
    3332             :         return GDK_FAIL;
    3333             : }
    3334             : 
    3335             : /* Count the number of unique values for the first half and the complete
    3336             :  * set (the sample s of b) and return the two values in *cnt1 and
    3337             :  * *cnt2. In case of error, both values are 0. */
    3338             : static gdk_return
    3339     1033505 : count_unique(BAT *b, BAT *s, BUN *cnt1, BUN *cnt2)
    3340             : {
    3341     1033505 :         struct canditer ci;
    3342     1033505 :         BUN half;
    3343     1033505 :         BUN cnt = 0;
    3344     1033505 :         const void *v;
    3345     1033505 :         const char *bvals;
    3346     1033505 :         const char *bvars;
    3347     1033505 :         oid bval;
    3348     1033505 :         oid i, o;
    3349     1033505 :         const char *nme;
    3350     1033505 :         BUN hb;
    3351     1033505 :         BATiter bi;
    3352     1033505 :         int (*cmp)(const void *, const void *);
    3353     1033505 :         const char *algomsg = "";
    3354     1033505 :         lng t0 = 0;
    3355             : 
    3356     1033505 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3357     1033505 :         canditer_init(&ci, b, s);
    3358     1033980 :         half = ci.ncand / 2;
    3359             : 
    3360     1033980 :         MT_lock_set(&b->theaplock);
    3361     1034051 :         if (b->tkey || ci.ncand <= 1 || BATtdense(b)) {
    3362             :                 /* trivial: already unique */
    3363        1425 :                 MT_lock_unset(&b->theaplock);
    3364        1425 :                 *cnt1 = half;
    3365        1425 :                 *cnt2 = ci.ncand;
    3366        1425 :                 return GDK_SUCCEED;
    3367             :         }
    3368     1032626 :         MT_lock_unset(&b->theaplock);
    3369             : 
    3370     1032742 :         (void) BATordered(b);
    3371     1032719 :         (void) BATordered_rev(b);
    3372     1032717 :         bi = bat_iterator(b);
    3373     1032419 :         if ((bi.sorted && bi.revsorted) ||
    3374      978668 :             (bi.type == TYPE_void && is_oid_nil(bi.tseq))) {
    3375             :                 /* trivial: all values are the same */
    3376       53751 :                 *cnt1 = *cnt2 = 1;
    3377       53751 :                 bat_iterator_end(&bi);
    3378       53751 :                 return GDK_SUCCEED;
    3379             :         }
    3380             : 
    3381      978668 :         assert(bi.type != TYPE_void);
    3382             : 
    3383      978668 :         bvals = bi.base;
    3384      978668 :         if (bi.vh && bi.type)
    3385       70301 :                 bvars = bi.vh->base;
    3386             :         else
    3387             :                 bvars = NULL;
    3388      978668 :         cmp = ATOMcompare(bi.type);
    3389             : 
    3390      978668 :         *cnt1 = *cnt2 = 0;
    3391             : 
    3392      978668 :         if (bi.sorted || bi.revsorted) {
    3393             :                 const void *prev = NULL;
    3394     9330739 :                 algomsg = "sorted";
    3395     9330739 :                 for (i = 0; i < ci.ncand; i++) {
    3396     9246781 :                         if (i == half)
    3397       83879 :                                 *cnt1 = cnt;
    3398     9246781 :                         o = canditer_next(&ci);
    3399     9247024 :                         v = VALUE(b, o - b->hseqbase);
    3400     9247024 :                         if (prev == NULL || (*cmp)(v, prev) != 0) {
    3401     3880973 :                                 cnt++;
    3402             :                         }
    3403     9246914 :                         prev = v;
    3404             :                 }
    3405       83958 :                 *cnt2 = cnt;
    3406      894843 :         } else if (ATOMbasetype(bi.type) == TYPE_bte) {
    3407       39990 :                 unsigned char val;
    3408       39990 :                 uint32_t seen[256 / 32];
    3409             : 
    3410       39990 :                 algomsg = "byte-sized atoms";
    3411       39990 :                 assert(bvars == NULL);
    3412       39990 :                 memset(seen, 0, sizeof(seen));
    3413     6632134 :                 for (i = 0; i < ci.ncand; i++) {
    3414     6592071 :                         if (i == ci.ncand/ 2) {
    3415             :                                 cnt = 0;
    3416      359063 :                                 for (int j = 0; j < 256 / 32; j++)
    3417      319000 :                                         cnt += candmask_pop(seen[j]);
    3418       40063 :                                 *cnt1 = cnt;
    3419             :                         }
    3420     6592071 :                         o = canditer_next(&ci);
    3421     6592144 :                         val = ((const unsigned char *) bvals)[o - b->hseqbase];
    3422     6592144 :                         if (!(seen[val >> 5] & (1U << (val & 0x1F)))) {
    3423       99974 :                                 seen[val >> 5] |= 1U << (val & 0x1F);
    3424             :                         }
    3425             :                 }
    3426             :                 cnt = 0;
    3427      359279 :                 for (int j = 0; j < 256 / 32; j++)
    3428      319216 :                         cnt += candmask_pop(seen[j]);
    3429       40063 :                 *cnt2 = cnt;
    3430      854853 :         } else if (ATOMbasetype(bi.type) == TYPE_sht) {
    3431       44796 :                 unsigned short val;
    3432       44796 :                 uint32_t *seen = NULL;
    3433             : 
    3434       44796 :                 algomsg = "short-sized atoms";
    3435       44796 :                 assert(bvars == NULL);
    3436       44796 :                 seen = GDKzalloc((65536 / 32) * sizeof(seen[0]));
    3437       44799 :                 if (seen == NULL) {
    3438           0 :                         bat_iterator_end(&bi);
    3439           0 :                         return GDK_FAIL;
    3440             :                 }
    3441     6988148 :                 for (i = 0; i < ci.ncand; i++) {
    3442     6943350 :                         if (i == half) {
    3443             :                                 cnt = 0;
    3444    91518717 :                                 for (int j = 0; j < 65536 / 32; j++)
    3445    91473920 :                                         cnt += candmask_pop(seen[j]);
    3446       44797 :                                 *cnt1 = cnt;
    3447             :                         }
    3448     6943350 :                         o = canditer_next(&ci);
    3449     6943349 :                         val = ((const unsigned short *) bvals)[o - b->hseqbase];
    3450     6943349 :                         if (!(seen[val >> 5] & (1U << (val & 0x1F)))) {
    3451      136362 :                                 seen[val >> 5] |= 1U << (val & 0x1F);
    3452             :                         }
    3453             :                 }
    3454             :                 cnt = 0;
    3455    91537150 :                 for (int j = 0; j < 65536 / 32; j++)
    3456    91492352 :                         cnt += candmask_pop(seen[j]);
    3457       44798 :                 *cnt2 = cnt;
    3458       44798 :                 GDKfree(seen);
    3459       44798 :                 seen = NULL;
    3460             :         } else {
    3461      810057 :                 BUN prb;
    3462      810057 :                 BUN mask;
    3463      810057 :                 Hash hs = {
    3464             :                         .heapbckt.parentid = b->batCacheid,
    3465      810057 :                         .heaplink.parentid = b->batCacheid,
    3466             :                 };
    3467             : 
    3468      810057 :                 GDKclrerr();    /* not interested in BAThash errors */
    3469      810054 :                 algomsg = "new partial hash";
    3470      810054 :                 nme = BBP_physical(b->batCacheid);
    3471      810054 :                 mask = HASHmask(ci.ncand);
    3472      593776 :                 if (mask < ((BUN) 1 << 16))
    3473      810054 :                         mask = (BUN) 1 << 16;
    3474      810054 :                 if ((hs.heaplink.farmid = BBPselectfarm(TRANSIENT, bi.type, hashheap)) < 0 ||
    3475      810056 :                     (hs.heapbckt.farmid = BBPselectfarm(TRANSIENT, bi.type, hashheap)) < 0 ||
    3476      810059 :                     snprintf(hs.heaplink.filename, sizeof(hs.heaplink.filename), "%s.thshjnl%x", nme, (unsigned) MT_getpid()) >= (int) sizeof(hs.heaplink.filename) ||
    3477     1620116 :                     snprintf(hs.heapbckt.filename, sizeof(hs.heapbckt.filename), "%s.thshjnb%x", nme, (unsigned) MT_getpid()) >= (int) sizeof(hs.heapbckt.filename) ||
    3478      810061 :                     HASHnew(&hs, bi.type, ci.ncand, mask, BUN_NONE, false) != GDK_SUCCEED) {
    3479           0 :                         GDKerror("cannot allocate hash table\n");
    3480           0 :                         HEAPfree(&hs.heaplink, true);
    3481           0 :                         HEAPfree(&hs.heapbckt, true);
    3482           0 :                         bat_iterator_end(&bi);
    3483           0 :                         return GDK_FAIL;
    3484             :                 }
    3485   405995247 :                 for (i = 0; i < ci.ncand; i++) {
    3486   405185191 :                         if (i == half)
    3487      810059 :                                 *cnt1 = cnt;
    3488   405185191 :                         o = canditer_next(&ci);
    3489   405179439 :                         v = VALUE(b, o - b->hseqbase);
    3490   405179439 :                         prb = HASHprobe(&hs, v);
    3491   405191589 :                         for (hb = HASHget(&hs, prb);
    3492   405211113 :                              hb != BUN_NONE;
    3493       19524 :                              hb = HASHgetlink(&hs, hb)) {
    3494   239730610 :                                 BUN p = canditer_idx(&ci, hb) - b->hseqbase;
    3495   239730610 :                                 if (cmp(v, BUNtail(bi, p)) == 0)
    3496             :                                         break;
    3497             :                         }
    3498   405175281 :                         if (hb == BUN_NONE) {
    3499   165470027 :                                 cnt++;
    3500             :                                 /* enter into hash table */
    3501   165470027 :                                 HASHputlink(&hs, i, HASHget(&hs, prb));
    3502   165479563 :                                 HASHput(&hs, prb, i);
    3503             :                         }
    3504             :                 }
    3505      810056 :                 *cnt2 = cnt;
    3506      810056 :                 HEAPfree(&hs.heaplink, true);
    3507      810038 :                 HEAPfree(&hs.heapbckt, true);
    3508             :         }
    3509      978865 :         bat_iterator_end(&bi);
    3510             : 
    3511      978658 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3512             :                   " -> " BUNFMT " " BUNFMT " (%s -- " LLFMT "usec)\n",
    3513             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3514             :                   *cnt1, *cnt2, algomsg, GDKusec() - t0);
    3515             : 
    3516             :         return GDK_SUCCEED;
    3517             : }
    3518             : 
    3519             : static double
    3520     2031730 : guess_uniques(BAT *b, struct canditer *ci)
    3521             : {
    3522     2031730 :         BUN cnt1, cnt2;
    3523     2031730 :         BAT *s1;
    3524             : 
    3525     2031730 :         MT_lock_set(&b->theaplock);
    3526     2032509 :         bool key = b->tkey;
    3527     2032509 :         double unique_est = b->tunique_est;
    3528     2032509 :         BUN batcount = BATcount(b);
    3529     2032509 :         MT_lock_unset(&b->theaplock);
    3530     2032673 :         if (key)
    3531      998415 :                 return (double) ci->ncand;
    3532             : 
    3533     1034258 :         if (ci->s == NULL ||
    3534           0 :             (ci->tpe == cand_dense && ci->ncand == batcount)) {
    3535     1034258 :                 if (unique_est != 0) {
    3536         206 :                         TRC_DEBUG(ALGO, "b=" ALGOBATFMT " use cached value\n",
    3537             :                                   ALGOBATPAR(b));
    3538         206 :                         return unique_est;
    3539             :                 }
    3540     1034052 :                 s1 = BATsample(b, 1000);
    3541             :         } else {
    3542           0 :                 BAT *s2 = BATsample(ci->s, 1000);
    3543           0 :                 if (s2 == NULL)
    3544             :                         return -1;
    3545           0 :                 s1 = BATproject(s2, ci->s);
    3546           0 :                 BBPreclaim(s2);
    3547             :         }
    3548     1033683 :         if (s1 == NULL)
    3549             :                 return -1;
    3550     1033683 :         BUN n2 = BATcount(s1);
    3551     1033683 :         BUN n1 = n2 / 2;
    3552     1033683 :         if (count_unique(b, s1, &cnt1, &cnt2) != GDK_SUCCEED) {
    3553           0 :                 BBPreclaim(s1);
    3554           0 :                 return -1;
    3555             :         }
    3556     1033805 :         BBPreclaim(s1);
    3557             : 
    3558     1034013 :         double A = (double) (cnt2 - cnt1) / (n2 - n1);
    3559     1034013 :         double B = cnt1 - n1 * A;
    3560             : 
    3561     1034013 :         B += A * ci->ncand;
    3562     1034013 :         MT_lock_set(&b->theaplock);
    3563     1033947 :         if (ci->s == NULL ||
    3564           0 :             (ci->tpe == cand_dense && ci->ncand == BATcount(b) && ci->ncand == batcount)) {
    3565     1033947 :                 if (b->tunique_est == 0)
    3566     1031746 :                         b->tunique_est = B;
    3567             :         }
    3568     1033947 :         MT_lock_unset(&b->theaplock);
    3569     1033953 :         return B;
    3570             : }
    3571             : 
    3572             : BUN
    3573     1253854 : BATguess_uniques(BAT *b, struct canditer *ci)
    3574             : {
    3575     1253854 :         struct canditer lci;
    3576     1253854 :         if (ci == NULL) {
    3577     1254095 :                 canditer_init(&lci, b, NULL);
    3578     1254095 :                 ci = &lci;
    3579             :         }
    3580     1254015 :         return (BUN) guess_uniques(b, ci);
    3581             : }
    3582             : 
    3583             : /* estimate the cost of doing a hashjoin with a hash on r; return value
    3584             :  * is the estimated cost, the last three arguments receive some extra
    3585             :  * information */
    3586             : double
    3587     1482047 : joincost(BAT *r, BUN lcount, struct canditer *rci,
    3588             :          bool *hash, bool *phash, bool *cand)
    3589             : {
    3590     1482047 :         bool rhash;
    3591     1482047 :         bool prhash = false;
    3592     1482047 :         bool rcand = false;
    3593     1482047 :         double rcost = 1;
    3594     1482047 :         bat parent;
    3595     1482047 :         BAT *b;
    3596     1482047 :         BUN nheads;
    3597     1482047 :         BUN cnt;
    3598             : 
    3599     1482047 :         (void) BATcheckhash(r);
    3600     1483206 :         MT_rwlock_rdlock(&r->thashlock);
    3601     1483153 :         rhash = r->thash != NULL;
    3602     1483153 :         nheads = r->thash ? r->thash->nheads : 0;
    3603     1483153 :         cnt = BATcount(r);
    3604     1483153 :         MT_rwlock_rdunlock(&r->thashlock);
    3605             : 
    3606     1482092 :         if ((rci->tpe == cand_materialized || rci->tpe == cand_except) &&
    3607      335255 :             rci->nvals > 0) {
    3608             :                 /* if we need to do binary search on candidate list,
    3609             :                  * take that into account; note checking the other
    3610             :                  * candidate types is essentially free */
    3611      335260 :                 rcost += log2((double) rci->nvals);
    3612             :         }
    3613     1482092 :         rcost *= lcount;
    3614     1482092 :         if (BATtdense(r)) {
    3615             :                 /* no need for a hash, and lookup is free */
    3616             :                 rhash = false;  /* don't use it, even if it's there */
    3617             :         } else {
    3618     1482091 :                 if (rhash) {
    3619             :                         /* average chain length */
    3620       10654 :                         rcost *= (double) cnt / nheads;
    3621     1471437 :                 } else if ((parent = VIEWtparent(r)) != 0 &&
    3622     1340444 :                            (b = BATdescriptor(parent)) != NULL) {
    3623     1340871 :                         if (BATcheckhash(b)) {
    3624       68445 :                                 MT_rwlock_rdlock(&b->thashlock);
    3625       68455 :                                 rhash = prhash = b->thash != NULL;
    3626       68455 :                                 if (rhash) {
    3627             :                                         /* average chain length */
    3628       68455 :                                         rcost *= (double) BATcount(b) / b->thash->nheads;
    3629             :                                 }
    3630       68455 :                                 MT_rwlock_rdunlock(&b->thashlock);
    3631             :                         }
    3632     1340873 :                         BBPunfix(b->batCacheid);
    3633             :                 }
    3634     1482442 :                 if (!rhash) {
    3635     1403425 :                         MT_lock_set(&r->theaplock);
    3636     1403966 :                         double unique_est = r->tunique_est;
    3637     1403966 :                         MT_lock_unset(&r->theaplock);
    3638     1404244 :                         if (unique_est == 0) {
    3639      778038 :                                 unique_est = guess_uniques(r, &(struct canditer){.tpe=cand_dense, .ncand=BATcount(r)});
    3640      777883 :                                 if (unique_est < 0)
    3641           0 :                                         return -1;
    3642             :                         }
    3643             :                         /* we have an estimate of the number of unique
    3644             :                          * values, assume some collisions */
    3645     1404089 :                         rcost *= 1.1 * ((double) cnt / unique_est);
    3646             :                         /* only count the cost of creating the hash for
    3647             :                          * non-persistent bats */
    3648     1404089 :                         MT_lock_set(&r->theaplock);
    3649     1403945 :                         if (r->batRole != PERSISTENT /* || r->theap->dirty */ || GDKinmemory(r->theap->farmid))
    3650     1375948 :                                 rcost += cnt * 2.0;
    3651     1403945 :                         MT_lock_unset(&r->theaplock);
    3652             :                 }
    3653             :         }
    3654     1483256 :         if (cand) {
    3655       38040 :                 if (rci->ncand != BATcount(r) && rci->tpe != cand_mask) {
    3656             :                         /* instead of using the hash on r (cost in
    3657             :                          * rcost), we can build a new hash on r taking
    3658             :                          * the candidate list into account; don't do
    3659             :                          * this for masked candidate since the searching
    3660             :                          * of the candidate list (canditer_idx) will
    3661             :                          * kill us */
    3662        2235 :                         double rccost;
    3663        2235 :                         if (rhash && !prhash) {
    3664         860 :                                 rccost = (double) cnt / nheads;
    3665             :                         } else {
    3666        1375 :                                 MT_lock_set(&r->theaplock);
    3667        1375 :                                 double unique_est = r->tunique_est;
    3668        1375 :                                 MT_lock_unset(&r->theaplock);
    3669        1375 :                                 if (unique_est == 0) {
    3670          83 :                                         unique_est = guess_uniques(r, rci);
    3671          83 :                                         if (unique_est < 0)
    3672             :                                                 return -1;
    3673             :                                 }
    3674             :                                 /* we have an estimate of the number of unique
    3675             :                                  * values, assume some chains */
    3676        1375 :                                 rccost = 1.1 * ((double) cnt / unique_est);
    3677             :                         }
    3678        2235 :                         rccost *= lcount;
    3679        2235 :                         rccost += rci->ncand * 2.0; /* cost of building the hash */
    3680        2235 :                         if (rccost < rcost) {
    3681       38040 :                                 rcost = rccost;
    3682       38040 :                                 rcand = true;
    3683             :                         }
    3684             :                 }
    3685       38040 :                 *cand = rcand;
    3686             :         }
    3687     1483256 :         *hash = rhash;
    3688     1483256 :         *phash = prhash;
    3689     1483256 :         return rcost;
    3690             : }
    3691             : 
    3692             : #define MASK_EQ         1
    3693             : #define MASK_LT         2
    3694             : #define MASK_GT         4
    3695             : #define MASK_LE         (MASK_EQ | MASK_LT)
    3696             : #define MASK_GE         (MASK_EQ | MASK_GT)
    3697             : #define MASK_NE         (MASK_LT | MASK_GT)
    3698             : 
    3699             : static gdk_return
    3700       50866 : thetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, int opcode,
    3701             :           BUN estimate, bool nil_matches, const char *reason, lng t0)
    3702             : {
    3703       50866 :         struct canditer lci, rci;
    3704       50866 :         const char *lvals, *rvals;
    3705       50866 :         const char *lvars, *rvars;
    3706       50866 :         const void *nil = ATOMnilptr(l->ttype);
    3707       50866 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    3708       50866 :         const void *vl, *vr;
    3709       50866 :         oid lastr = 0;          /* last value inserted into r2 */
    3710       50866 :         BUN nr;
    3711       50866 :         oid lo, ro;
    3712       50866 :         int c;
    3713       50866 :         bool lskipped = false;  /* whether we skipped values in l */
    3714       50866 :         lng loff = 0, roff = 0;
    3715       50866 :         oid lval = oid_nil, rval = oid_nil;
    3716             : 
    3717       50866 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    3718             : 
    3719      152577 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    3720       50859 :         assert((opcode & (MASK_EQ | MASK_LT | MASK_GT)) != 0);
    3721             : 
    3722       50859 :         BATiter li = bat_iterator(l);
    3723       50992 :         BATiter ri = bat_iterator(r);
    3724             : 
    3725       50999 :         canditer_init(&lci, l, sl);
    3726       50945 :         canditer_init(&rci, r, sr);
    3727             : 
    3728       50813 :         lvals = BATtvoid(l) ? NULL : (const char *) li.base;
    3729       50813 :         rvals = BATtvoid(r) ? NULL : (const char *) ri.base;
    3730       50813 :         if (li.vh && li.type) {
    3731          16 :                 assert(ri.vh && ri.type);
    3732          16 :                 lvars = li.vh->base;
    3733          16 :                 rvars = ri.vh->base;
    3734             :         } else {
    3735       50797 :                 assert(ri.vh == NULL);
    3736             :                 lvars = rvars = NULL;
    3737             :         }
    3738             : 
    3739       50813 :         if (BATtvoid(l)) {
    3740           0 :                 if (!BATtdensebi(&li)) {
    3741           0 :                         if (!nil_matches) {
    3742             :                                 /* trivial: nils don't match anything */
    3743           0 :                                 bat_iterator_end(&li);
    3744           0 :                                 bat_iterator_end(&ri);
    3745           0 :                                 return nomatch(r1p, r2p, NULL, l, r, &lci,
    3746             :                                                0, false, false, __func__, t0);
    3747             :                         }
    3748             :                 } else {
    3749           0 :                         loff = (lng) l->tseqbase - (lng) l->hseqbase;
    3750             :                 }
    3751             :         }
    3752       50813 :         if (BATtvoid(r)) {
    3753           1 :                 if (!BATtdensebi(&ri)) {
    3754           0 :                         if (!nil_matches) {
    3755             :                                 /* trivial: nils don't match anything */
    3756           0 :                                 bat_iterator_end(&li);
    3757           0 :                                 bat_iterator_end(&ri);
    3758           0 :                                 return nomatch(r1p, r2p, NULL, l, r, &lci,
    3759             :                                                0, false, false, __func__, t0);
    3760             :                         }
    3761             :                 } else {
    3762           1 :                         roff = (lng) r->tseqbase - (lng) r->hseqbase;
    3763             :                 }
    3764             :         }
    3765             : 
    3766       50813 :         BUN maxsize = joininitresults(r1p, r2p, NULL, lci.ncand, rci.ncand, false, false,
    3767             :                                       false, false, false, false, estimate);
    3768       50123 :         if (maxsize == BUN_NONE) {
    3769           0 :                 bat_iterator_end(&li);
    3770           0 :                 bat_iterator_end(&ri);
    3771           0 :                 return GDK_FAIL;
    3772             :         }
    3773       50123 :         BAT *r1 = *r1p;
    3774       50123 :         BAT *r2 = r2p ? *r2p : NULL;
    3775             : 
    3776       50123 :         r1->tkey = true;
    3777       50123 :         r1->tsorted = true;
    3778       50123 :         r1->trevsorted = true;
    3779       50123 :         if (r2) {
    3780        8327 :                 r2->tkey = true;
    3781        8327 :                 r2->tsorted = true;
    3782        8327 :                 r2->trevsorted = true;
    3783             :         }
    3784             : 
    3785             :         /* nested loop implementation for theta join */
    3786             :         vl = &lval;
    3787             :         vr = &rval;
    3788      352457 :         for (BUN lidx = 0; lidx < lci.ncand; lidx++) {
    3789      301811 :                 lo = canditer_next(&lci);
    3790      292824 :                 if (lvals)
    3791      292824 :                         vl = VALUE(l, lo - l->hseqbase);
    3792           0 :                 else if (BATtdensebi(&li))
    3793           0 :                         lval = (oid) ((lng) lo + loff);
    3794      292824 :                 nr = 0;
    3795      292824 :                 if (nil_matches || cmp(vl, nil) != 0) {
    3796      285639 :                         canditer_reset(&rci);
    3797     3604934 :                         TIMEOUT_LOOP(rci.ncand, qry_ctx) {
    3798     3040275 :                                 ro = canditer_next(&rci);
    3799     2978868 :                                 if (rvals)
    3800     2978864 :                                         vr = VALUE(r, ro - r->hseqbase);
    3801           4 :                                 else if (BATtdensebi(&ri))
    3802           4 :                                         rval = (oid) ((lng) ro + roff);
    3803     2978868 :                                 if (!nil_matches && cmp(vr, nil) == 0)
    3804       59603 :                                         continue;
    3805     2916943 :                                 c = cmp(vl, vr);
    3806     2954700 :                                 if (!((opcode & MASK_LT && c < 0) ||
    3807     2751977 :                                       (opcode & MASK_GT && c > 0) ||
    3808     1492852 :                                       (opcode & MASK_EQ && c == 0)))
    3809     1492832 :                                         continue;
    3810     1461868 :                                 if (maybeextend(r1, r2, NULL, 1, lci.next, lci.ncand, maxsize) != GDK_SUCCEED)
    3811           0 :                                         goto bailout;
    3812     1483595 :                                 if (BATcount(r1) > 0) {
    3813     1462303 :                                         if (r2 && lastr + 1 != ro)
    3814       54136 :                                                 r2->tseqbase = oid_nil;
    3815     1462303 :                                         if (nr == 0) {
    3816      153010 :                                                 r1->trevsorted = false;
    3817      153010 :                                                 if (r2 == NULL) {
    3818             :                                                         /* nothing */
    3819       44276 :                                                 } else if (lastr > ro) {
    3820       40846 :                                                         r2->tsorted = false;
    3821       40846 :                                                         r2->tkey = false;
    3822        3430 :                                                 } else if (lastr < ro) {
    3823           0 :                                                         r2->trevsorted = false;
    3824             :                                                 } else {
    3825        3430 :                                                         r2->tkey = false;
    3826             :                                                 }
    3827             :                                         }
    3828             :                                 }
    3829     1483595 :                                 APPEND(r1, lo);
    3830     1483595 :                                 if (r2) {
    3831     1202414 :                                         APPEND(r2, ro);
    3832             :                                 }
    3833     1483595 :                                 lastr = ro;
    3834     1483595 :                                 nr++;
    3835             :                         }
    3836      283513 :                         TIMEOUT_CHECK(qry_ctx,
    3837             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    3838             :                 }
    3839      302334 :                 if (nr > 1) {
    3840      146375 :                         r1->tkey = false;
    3841      146375 :                         r1->tseqbase = oid_nil;
    3842      146375 :                         if (r2) {
    3843       47278 :                                 r2->trevsorted = false;
    3844             :                         }
    3845      155959 :                 } else if (nr == 0) {
    3846      122806 :                         lskipped = BATcount(r1) > 0;
    3847       33153 :                 } else if (lskipped) {
    3848       20928 :                         r1->tseqbase = oid_nil;
    3849             :                 }
    3850             :         }
    3851             :         /* also set other bits of heap to correct value to indicate size */
    3852       50646 :         BATsetcount(r1, BATcount(r1));
    3853       50269 :         if (r2) {
    3854        8396 :                 BATsetcount(r2, BATcount(r2));
    3855        8426 :                 assert(BATcount(r1) == BATcount(r2));
    3856             :         }
    3857       50299 :         if (BATcount(r1) > 0) {
    3858       25293 :                 if (BATtdense(r1))
    3859        1240 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    3860       25293 :                 if (r2 && BATtdense(r2))
    3861        1012 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    3862             :         } else {
    3863       25006 :                 r1->tseqbase = 0;
    3864       25006 :                 if (r2) {
    3865        1666 :                         r2->tseqbase = 0;
    3866             :                 }
    3867             :         }
    3868       50299 :         bat_iterator_end(&li);
    3869       50802 :         bat_iterator_end(&ri);
    3870       50073 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT
    3871             :                   ",sl=" ALGOOPTBATFMT "," "sr=" ALGOOPTBATFMT ","
    3872             :                   "opcode=%s%s%s; %s -> " ALGOBATFMT "," ALGOOPTBATFMT
    3873             :                   " (" LLFMT "usec)\n",
    3874             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    3875             :                   ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    3876             :                   opcode & MASK_LT ? "<" : "",
    3877             :                   opcode & MASK_GT ? ">" : "",
    3878             :                   opcode & MASK_EQ ? "=" : "",
    3879             :                   reason,
    3880             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    3881             :                   GDKusec() - t0);
    3882             :         return GDK_SUCCEED;
    3883             : 
    3884           0 :   bailout:
    3885           0 :         bat_iterator_end(&li);
    3886           0 :         bat_iterator_end(&ri);
    3887           0 :         BBPreclaim(r1);
    3888           0 :         BBPreclaim(r2);
    3889             :         return GDK_FAIL;
    3890             : }
    3891             : 
    3892             : /* small ordered right, dense left, oid's only, do fetches */
    3893             : static gdk_return
    3894           0 : fetchjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    3895             :           struct canditer *restrict lci, struct canditer *restrict rci,
    3896             :           const char *reason, lng t0)
    3897             : {
    3898           0 :         oid lo = lci->seq - l->hseqbase + l->tseqbase, hi = lo + lci->ncand;
    3899           0 :         BUN b, e, p;
    3900           0 :         BAT *r1, *r2 = NULL;
    3901             : 
    3902           0 :         MT_thread_setalgorithm(__func__);
    3903           0 :         if (r->tsorted) {
    3904           0 :                 b = SORTfndfirst(r, &lo);
    3905           0 :                 e = SORTfndfirst(r, &hi);
    3906             :         } else {
    3907           0 :                 assert(r->trevsorted);
    3908           0 :                 b = SORTfndlast(r, &hi);
    3909           0 :                 e = SORTfndlast(r, &lo);
    3910             :         }
    3911           0 :         if (b < rci->seq - r->hseqbase)
    3912             :                 b = rci->seq - r->hseqbase;
    3913           0 :         if (e > rci->seq + rci->ncand - r->hseqbase)
    3914             :                 e = rci->seq + rci->ncand - r->hseqbase;
    3915           0 :         if (e == b) {
    3916           0 :                 return nomatch(r1p, r2p, NULL, l, r, lci,
    3917             :                                0, false, false, __func__, t0);
    3918             :         }
    3919           0 :         r1 = COLnew(0, TYPE_oid, e - b, TRANSIENT);
    3920           0 :         if (r1 == NULL)
    3921             :                 return GDK_FAIL;
    3922           0 :         if (r2p) {
    3923           0 :                 if ((r2 = BATdense(0, r->hseqbase + b, e - b)) == NULL) {
    3924           0 :                         BBPreclaim(r1);
    3925           0 :                         return GDK_FAIL;
    3926             :                 }
    3927           0 :                 *r2p = r2;
    3928             :         }
    3929           0 :         *r1p = r1;
    3930           0 :         oid *op = (oid *) Tloc(r1, 0);
    3931           0 :         BATiter ri = bat_iterator(r);
    3932           0 :         const oid *rp = (const oid *) ri.base;
    3933           0 :         for (p = b; p < e; p++) {
    3934           0 :                 *op++ = rp[p] + l->hseqbase - l->tseqbase;
    3935             :         }
    3936           0 :         BATsetcount(r1, e - b);
    3937           0 :         r1->tkey = ri.key;
    3938           0 :         r1->tsorted = ri.sorted || e - b <= 1;
    3939           0 :         r1->trevsorted = ri.revsorted || e - b <= 1;
    3940           0 :         r1->tseqbase = e == b ? 0 : e - b == 1 ? *(const oid *)Tloc(r1, 0) : oid_nil;
    3941           0 :         bat_iterator_end(&ri);
    3942           0 :         TRC_DEBUG(ALGO, "%s(l=" ALGOBATFMT ","
    3943             :                   "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    3944             :                   "sr=" ALGOOPTBATFMT ") %s "
    3945             :                   "-> (" ALGOBATFMT "," ALGOOPTBATFMT ") " LLFMT "us\n",
    3946             :                   __func__,
    3947             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    3948             :                   ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    3949             :                   reason,
    3950             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    3951             :                   GDKusec() - t0);
    3952             : 
    3953             :         return GDK_SUCCEED;
    3954             : }
    3955             : 
    3956             : static BAT *
    3957        5187 : bitmaskjoin(BAT *l, BAT *r,
    3958             :             struct canditer *restrict lci, struct canditer *restrict rci,
    3959             :             bool only_misses,
    3960             :             const char *reason, lng t0)
    3961             : {
    3962        5187 :         BAT *r1;
    3963        5187 :         size_t nmsk = (lci->ncand + 31) / 32;
    3964        5187 :         uint32_t *mask = GDKzalloc(nmsk * sizeof(uint32_t));
    3965        5190 :         BUN cnt = 0;
    3966             : 
    3967        5190 :         MT_thread_setalgorithm(__func__);
    3968        5190 :         if (mask == NULL)
    3969             :                 return NULL;
    3970             : 
    3971    22122556 :         for (BUN n = 0; n < rci->ncand; n++) {
    3972    22117366 :                 oid o = canditer_next(rci) - r->hseqbase;
    3973    22117366 :                 o = BUNtoid(r, o);
    3974    22117366 :                 if (is_oid_nil(o))
    3975           0 :                         continue;
    3976    22117366 :                 o += l->hseqbase;
    3977    22117366 :                 if (o < lci->seq + l->tseqbase)
    3978           2 :                         continue;
    3979    22117364 :                 o -= lci->seq + l->tseqbase;
    3980    22117364 :                 if (o >= lci->ncand)
    3981           0 :                         continue;
    3982    22117364 :                 if ((mask[o >> 5] & (1U << (o & 0x1F))) == 0) {
    3983    16661414 :                         cnt++;
    3984    16661414 :                         mask[o >> 5] |= 1U << (o & 0x1F);
    3985             :                 }
    3986             :         }
    3987        5190 :         if (only_misses)
    3988        3680 :                 cnt = lci->ncand - cnt;
    3989        5190 :         if (cnt == 0 || cnt == lci->ncand) {
    3990        1516 :                 GDKfree(mask);
    3991        1516 :                 if (cnt == 0)
    3992         364 :                         return BATdense(0, 0, 0);
    3993        1152 :                 return BATdense(0, lci->seq, lci->ncand);
    3994             :         }
    3995        3674 :         r1 = COLnew(0, TYPE_oid, cnt, TRANSIENT);
    3996        3674 :         if (r1 != NULL) {
    3997        3674 :                 oid *r1p = Tloc(r1, 0);
    3998             : 
    3999        3674 :                 r1->tkey = true;
    4000        3674 :                 r1->tnil = false;
    4001        3674 :                 r1->tnonil = true;
    4002        3674 :                 r1->tsorted = true;
    4003        3674 :                 r1->trevsorted = cnt <= 1;
    4004        3674 :                 if (only_misses) {
    4005             :                         /* set the bits for unused values at the
    4006             :                          * end so that we don't need special
    4007             :                          * code in the loop */
    4008        3316 :                         if (lci->ncand & 0x1F)
    4009        3244 :                                 mask[nmsk - 1] |= ~0U << (lci->ncand & 0x1F);
    4010     1984396 :                         for (size_t i = 0; i < nmsk; i++)
    4011     1981080 :                                 if (mask[i] != ~0U)
    4012    62627169 :                                         for (uint32_t j = 0; j < 32; j++)
    4013    60729376 :                                                 if ((mask[i] & (1U << j)) == 0)
    4014    53990976 :                                                         *r1p++ = i * 32 + j + lci->seq;
    4015             :                 } else {
    4016      313125 :                         for (size_t i = 0; i < nmsk; i++)
    4017      312767 :                                 if (mask[i] != 0U)
    4018     7940922 :                                         for (uint32_t j = 0; j < 32; j++)
    4019     7700288 :                                                 if ((mask[i] & (1U << j)) != 0)
    4020     6936215 :                                                         *r1p++ = i * 32 + j + lci->seq;
    4021             :                 }
    4022        3674 :                 BATsetcount(r1, cnt);
    4023        3674 :                 assert((BUN) (r1p - (oid*) Tloc(r1, 0)) == BATcount(r1));
    4024             : 
    4025        3674 :                 TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
    4026             :                           "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    4027             :                           "sr=" ALGOOPTBATFMT ",only_misses=%s; %s "
    4028             :                           "-> " ALGOBATFMT " (" LLFMT "usec)\n",
    4029             :                           ALGOBATPAR(l), ALGOBATPAR(r),
    4030             :                           ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    4031             :                           only_misses ? "true" : "false",
    4032             :                           reason,
    4033             :                           ALGOBATPAR(r1),
    4034             :                           GDKusec() - t0);
    4035             :         }
    4036        3674 :         GDKfree(mask);
    4037        3674 :         return r1;
    4038             : }
    4039             : 
    4040             : /* Make the implementation choices for various left joins.
    4041             :  * 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
    4042             :  * nil_matches: nil is an ordinary value that can match;
    4043             :  * nil_on_miss: outer join: fill in a nil value in case of no match;
    4044             :  * semi: semi join: return one of potentially more than one matches;
    4045             :  * only_misses: difference: list rows without match on the right;
    4046             :  * not_in: for implementing NOT IN: if nil on right then there are no matches;
    4047             :  * max_one: error if there is more than one match;
    4048             :  * min_one: error if there are no matches. */
    4049             : static gdk_return
    4050      192443 : leftjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4051             :          bool nil_matches, bool nil_on_miss, bool semi, bool only_misses,
    4052             :          bool not_in, bool max_one, bool min_one, BUN estimate,
    4053             :          const char *func, lng t0)
    4054             : {
    4055      192443 :         struct canditer lci, rci;
    4056      192443 :         bool rhash, prhash, rcand;
    4057      192443 :         bat parent;
    4058      192443 :         double rcost = 0;
    4059      192443 :         gdk_return rc;
    4060      192443 :         BAT *lp = NULL;
    4061      192443 :         BAT *rp = NULL;
    4062             : 
    4063      192443 :         MT_thread_setalgorithm(__func__);
    4064             :         /* only_misses implies left output only */
    4065      192362 :         assert(!only_misses || r2p == NULL);
    4066             :         /* if nil_on_miss is set, we really need a right output */
    4067      192362 :         assert(!nil_on_miss || r2p != NULL || r3p != NULL);
    4068             :         /* if not_in is set, then so is only_misses */
    4069      192362 :         assert(!not_in || only_misses);
    4070             :         /* if r3p is set, then so is nil_on_miss */
    4071      192362 :         assert(r3p == NULL || nil_on_miss);
    4072      192362 :         *r1p = NULL;
    4073      192362 :         if (r2p)
    4074        1047 :                 *r2p = NULL;
    4075      192362 :         if (r3p)
    4076       19386 :                 *r3p = NULL;
    4077             : 
    4078      192362 :         canditer_init(&lci, l, sl);
    4079      193046 :         canditer_init(&rci, r, sr);
    4080             : 
    4081      193106 :         if ((parent = VIEWtparent(l)) != 0) {
    4082        4005 :                 lp = BATdescriptor(parent);
    4083        4009 :                 if (lp == NULL)
    4084             :                         return GDK_FAIL;
    4085        4009 :                 if (l->hseqbase == lp->hseqbase &&
    4086        4572 :                     BATcount(l) == BATcount(lp) &&
    4087        3246 :                     ATOMtype(l->ttype) == ATOMtype(lp->ttype)) {
    4088             :                         l = lp;
    4089             :                 } else {
    4090        2386 :                         BBPunfix(lp->batCacheid);
    4091        2386 :                         lp = NULL;
    4092             :                 }
    4093             :         }
    4094      193109 :         if ((parent = VIEWtparent(r)) != 0) {
    4095        4355 :                 rp = BATdescriptor(parent);
    4096        4356 :                 if (rp == NULL) {
    4097           0 :                         BBPreclaim(lp);
    4098           0 :                         return GDK_FAIL;
    4099             :                 }
    4100        4356 :                 if (r->hseqbase == rp->hseqbase &&
    4101        7185 :                     BATcount(r) == BATcount(rp) &&
    4102        5658 :                     ATOMtype(r->ttype) == ATOMtype(rp->ttype)) {
    4103             :                         r = rp;
    4104             :                 } else {
    4105        1530 :                         BBPunfix(rp->batCacheid);
    4106        1530 :                         rp = NULL;
    4107             :                 }
    4108             :         }
    4109             : 
    4110      193109 :         if (l->ttype == TYPE_msk || mask_cand(l)) {
    4111           5 :                 l = BATunmask(l);
    4112           5 :                 BBPreclaim(lp);
    4113           5 :                 if (l == NULL) {
    4114           0 :                         BBPreclaim(rp);
    4115           0 :                         return GDK_FAIL;
    4116             :                 }
    4117             :                 lp = l;
    4118             :         }
    4119      193109 :         if (r->ttype == TYPE_msk || mask_cand(r)) {
    4120          66 :                 r = BATunmask(r);
    4121          66 :                 BBPreclaim(rp);
    4122          66 :                 if (r == NULL) {
    4123           0 :                         BBPreclaim(lp);
    4124           0 :                         return GDK_FAIL;
    4125             :                 }
    4126             :                 rp = r;
    4127             :         }
    4128             : 
    4129      193109 :         if (joinparamcheck(l, r, NULL, sl, sr, func) != GDK_SUCCEED) {
    4130           0 :                 rc = GDK_FAIL;
    4131           0 :                 goto doreturn;
    4132             :         }
    4133             : 
    4134      192748 :         if (lci.ncand == 0 || rci.ncand == 0) {
    4135      153648 :                 TRC_DEBUG(ALGO, "%s(l=" ALGOBATFMT ","
    4136             :                           "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    4137             :                           "sr=" ALGOOPTBATFMT ",nil_matches=%d,"
    4138             :                           "nil_on_miss=%d,semi=%d,only_misses=%d,"
    4139             :                           "not_in=%d,max_one=%d,min_one=%d)\n",
    4140             :                           func,
    4141             :                           ALGOBATPAR(l), ALGOBATPAR(r),
    4142             :                           ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    4143             :                           nil_matches, nil_on_miss, semi, only_misses,
    4144             :                           not_in, max_one, min_one);
    4145      153648 :                 rc = nomatch(r1p, r2p, r3p, l, r, &lci,
    4146             :                              0, nil_on_miss, only_misses, func, t0);
    4147      153490 :                 goto doreturn;
    4148             :         }
    4149             : 
    4150       39100 :         if (!only_misses && !not_in &&
    4151        4277 :             (lci.ncand == 1 || (BATordered(l) && BATordered_rev(l)) ||
    4152        4223 :              (l->ttype == TYPE_void && is_oid_nil(l->tseqbase)))) {
    4153             :                 /* single value to join, use select */
    4154        1725 :                 rc = selectjoin(r1p, r2p, r3p, l, r, &lci, &rci,
    4155             :                                 nil_matches, nil_on_miss, semi, max_one, min_one,
    4156             :                                 t0, false, func);
    4157        1720 :                 goto doreturn;
    4158       37390 :         } else if (BATtdense(r) && rci.tpe == cand_dense) {
    4159             :                 /* use special implementation for dense right-hand side */
    4160       25078 :                 rc = mergejoin_void(r1p, r2p, r3p, l, r, &lci, &rci,
    4161             :                                     nil_on_miss, only_misses, t0, false,
    4162             :                                     func);
    4163       25016 :                 goto doreturn;
    4164       12312 :         } else if (BATtdense(l)
    4165        5266 :                    && lci.tpe == cand_dense
    4166        5245 :                    && rci.tpe == cand_dense
    4167             :                    && !semi
    4168        5245 :                    && !max_one
    4169             :                    && !min_one
    4170        3693 :                    && !nil_matches
    4171             :                    && !only_misses
    4172        3695 :                    && !not_in
    4173             :                    /* && (rci.ncand * 1024) < lci.ncand */
    4174           0 :                    && (BATordered(r) || BATordered_rev(r))) {
    4175           0 :                 assert(ATOMtype(l->ttype) == TYPE_oid); /* tdense */
    4176           0 :                 rc = fetchjoin(r1p, r2p, l, r, sl, sr, &lci, &rci, func, t0);
    4177           0 :                 goto doreturn;
    4178       12312 :         } else if (BATtdense(l)
    4179        5269 :                    && lci.tpe == cand_dense
    4180        5248 :                    && r2p == NULL
    4181        5206 :                    && (semi || only_misses)
    4182             :                    && !nil_on_miss
    4183        5206 :                    && !not_in
    4184             :                    && !max_one
    4185        5191 :                    && !min_one) {
    4186        5190 :                 *r1p = bitmaskjoin(l, r, &lci, &rci, only_misses, func, t0);
    4187        5188 :                 rc = *r1p == NULL ? GDK_FAIL : GDK_SUCCEED;
    4188        5188 :                 goto doreturn;
    4189             :         } else {
    4190             :                 /* looking at r->tvheap, so we need a lock */
    4191        7122 :                 MT_lock_set(&r->theaplock);
    4192        7134 :                 BUN hsz = r->tvheap ? r->tvheap->size : 0;
    4193        7134 :                 MT_lock_unset(&r->theaplock);
    4194        7134 :                 if ((BATordered(r) || BATordered_rev(r))
    4195        5118 :                     && (BATordered(l)
    4196         584 :                         || BATordered_rev(l)
    4197         538 :                         || BATtdense(r)
    4198         538 :                         || lci.ncand < 1024
    4199         248 :                         || BATcount(r) * (r->twidth + hsz + 2 * sizeof(BUN)) > GDK_mem_maxsize / (GDKnr_threads ? GDKnr_threads : 1))) {
    4200        4994 :                         rc = mergejoin(r1p, r2p, r3p, l, r, &lci, &rci,
    4201             :                                        nil_matches, nil_on_miss, semi, only_misses,
    4202             :                                        not_in, max_one, min_one, estimate, t0, false, func);
    4203        4924 :                         goto doreturn;
    4204             :                 }
    4205             :         }
    4206        2143 :         rcost = joincost(r, lci.ncand, &rci, &rhash, &prhash, &rcand);
    4207        2132 :         if (rcost < 0) {
    4208           0 :                 rc = GDK_FAIL;
    4209           0 :                 goto doreturn;
    4210             :         }
    4211             : 
    4212        2132 :         if (!nil_on_miss && !only_misses && !not_in && !max_one && !min_one) {
    4213             :                 /* maybe do a hash join on the swapped operands; if we
    4214             :                  * do, we need to sort the output, so we take that into
    4215             :                  * account as well */
    4216         958 :                 bool lhash, plhash, lcand, rkey = r->tkey;
    4217         958 :                 double lcost;
    4218             : 
    4219         958 :                 lcost = joincost(l, rci.ncand, &lci, &lhash, &plhash, &lcand);
    4220         957 :                 if (lcost < 0) {
    4221           0 :                         rc = GDK_FAIL;
    4222         823 :                         goto doreturn;
    4223             :                 }
    4224         957 :                 if (semi && !rkey)
    4225         842 :                         lcost += rci.ncand; /* cost of BATunique(r) */
    4226             :                 /* add cost of sorting; obviously we don't know the
    4227             :                  * size, so we guess that the size of the output is
    4228             :                  * the same as the right input */
    4229         957 :                 lcost += rci.ncand * log((double) rci.ncand); /* sort */
    4230         957 :                 if (lcost < rcost) {
    4231         823 :                         BAT *tmp = sr;
    4232         823 :                         BAT *r1, *r2;
    4233         823 :                         if (semi && !rkey) {
    4234         818 :                                 sr = BATunique(r, sr);
    4235         818 :                                 if (sr == NULL) {
    4236           0 :                                         rc = GDK_FAIL;
    4237           0 :                                         goto doreturn;
    4238             :                                 }
    4239         818 :                                 canditer_init(&rci, r, sr);
    4240             :                         }
    4241         823 :                         rc = hashjoin(&r2, &r1, NULL, r, l, &rci, &lci, nil_matches,
    4242             :                                       false, false, false, false, false, false, estimate,
    4243             :                                       t0, true, lhash, plhash, lcand, func);
    4244         823 :                         if (semi && !rkey)
    4245         818 :                                 BBPunfix(sr->batCacheid);
    4246         823 :                         if (rc != GDK_SUCCEED)
    4247           0 :                                 goto doreturn;
    4248         823 :                         if (r2p == NULL) {
    4249         818 :                                 BBPunfix(r2->batCacheid);
    4250         818 :                                 r2 = NULL;
    4251             :                         }
    4252         823 :                         if (semi)
    4253         818 :                                 r1->tkey = true;
    4254         823 :                         if (!VIEWtparent(r1) &&
    4255         823 :                             r1->ttype == TYPE_oid &&
    4256         823 :                             BBP_refs(r1->batCacheid) == 1 &&
    4257         823 :                             (r2 == NULL ||
    4258           5 :                              (!VIEWtparent(r2) &&
    4259           5 :                               BBP_refs(r2->batCacheid) == 1 &&
    4260           5 :                               r2->ttype == TYPE_oid))) {
    4261             :                                 /* in-place sort if we can */
    4262         823 :                                 if (r2) {
    4263           5 :                                         GDKqsort(r1->theap->base, r2->theap->base,
    4264           5 :                                                  NULL, r1->batCount, r1->twidth,
    4265           5 :                                                  r2->twidth, TYPE_oid, false,
    4266             :                                                  false);
    4267           5 :                                         r2->tsorted = false;
    4268           5 :                                         r2->trevsorted = false;
    4269           5 :                                         r2->tseqbase = oid_nil;
    4270           5 :                                         *r2p = r2;
    4271             :                                 } else {
    4272         818 :                                         GDKqsort(r1->theap->base, NULL, NULL,
    4273         818 :                                                  r1->batCount, r1->twidth, 0,
    4274             :                                                  TYPE_oid, false, false);
    4275             :                                 }
    4276         823 :                                 r1->tsorted = true;
    4277         823 :                                 r1->trevsorted = false;
    4278         823 :                                 *r1p = r1;
    4279             :                         } else {
    4280           0 :                                 BAT *ob;
    4281           0 :                                 rc = BATsort(&tmp, r2p ? &ob : NULL, NULL,
    4282             :                                              r1, NULL, NULL, false, false, false);
    4283           0 :                                 BBPunfix(r1->batCacheid);
    4284           0 :                                 if (rc != GDK_SUCCEED) {
    4285           0 :                                         BBPreclaim(r2);
    4286           0 :                                         goto doreturn;
    4287             :                                 }
    4288           0 :                                 *r1p = r1 = tmp;
    4289           0 :                                 if (r2p) {
    4290           0 :                                         tmp = BATproject(ob, r2);
    4291           0 :                                         BBPunfix(r2->batCacheid);
    4292           0 :                                         BBPunfix(ob->batCacheid);
    4293           0 :                                         if (tmp == NULL) {
    4294           0 :                                                 BBPunfix(r1->batCacheid);
    4295           0 :                                                 rc = GDK_FAIL;
    4296           0 :                                                 goto doreturn;
    4297             :                                         }
    4298           0 :                                         *r2p = tmp;
    4299             :                                 }
    4300             :                         }
    4301         823 :                         rc = GDK_SUCCEED;
    4302         823 :                         goto doreturn;
    4303             :                 }
    4304             :         }
    4305        1308 :         rc = hashjoin(r1p, r2p, r3p, l, r, &lci, &rci,
    4306             :                       nil_matches, nil_on_miss, semi, only_misses,
    4307             :                       not_in, max_one, min_one, estimate, t0, false, rhash, prhash,
    4308             :                       rcand, func);
    4309      192462 :   doreturn:
    4310      192462 :         BBPreclaim(lp);
    4311      192404 :         BBPreclaim(rp);
    4312      192820 :         if (rc == GDK_SUCCEED && (semi | only_misses))
    4313      191941 :                 *r1p = virtualize(*r1p);
    4314             :         return rc;
    4315             : }
    4316             : 
    4317             : /* Perform an equi-join over l and r.  Returns two new, aligned, bats
    4318             :  * with the oids of matching tuples.  The result is in the same order
    4319             :  * as l (i.e. r1 is sorted). */
    4320             : gdk_return
    4321         645 : BATleftjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, BUN estimate)
    4322             : {
    4323         645 :         return leftjoin(r1p, r2p, NULL, l, r, sl, sr, nil_matches,
    4324             :                         false, false, false, false, false, false,
    4325             :                         estimate, __func__,
    4326         645 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4327             : }
    4328             : 
    4329             : /* Performs a left outer join over l and r.  Returns two new, aligned,
    4330             :  * bats with the oids of matching tuples, or the oid in the first
    4331             :  * output bat and nil in the second output bat if the value in l does
    4332             :  * not occur in r.  The result is in the same order as l (i.e. r1 is
    4333             :  * sorted). */
    4334             : gdk_return
    4335         123 : BATouterjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, bool match_one, BUN estimate)
    4336             : {
    4337         123 :         return leftjoin(r1p, r2p, NULL, l, r, sl, sr, nil_matches,
    4338             :                         true, false, false, false, match_one, match_one,
    4339             :                         estimate, __func__,
    4340         123 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4341             : }
    4342             : 
    4343             : /* Perform a semi-join over l and r.  Returns one or two new bats
    4344             :  * with the oids of matching tuples.  The result is in the same order
    4345             :  * as l (i.e. r1 is sorted).  If a single bat is returned, it is a
    4346             :  * candidate list. */
    4347             : gdk_return
    4348        1079 : BATsemijoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4349             :             bool nil_matches, bool max_one, BUN estimate)
    4350             : {
    4351        1079 :         return leftjoin(r1p, r2p, NULL, l, r, sl, sr, nil_matches,
    4352             :                         false, true, false, false, max_one, false,
    4353             :                         estimate, __func__,
    4354        1079 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4355             : }
    4356             : 
    4357             : /* Perform a mark-join over l and r.  Returns one or two new bats with
    4358             :  * the oids of matching tuples.  In addition, returns a bat with "marks"
    4359             :  * that indicate the type of match.  This is an outer join, so returns
    4360             :  * at least one value for each row on the left.  If the second output
    4361             :  * pointer (r2p) is NULL, this is also a semi-join, so returns exactly
    4362             :  * one row for each row on the left.  If there is a match, the mark
    4363             :  * column will be TRUE, of there is no match, the second output is NIL,
    4364             :  * and the mark output is FALSE if there are no NILs in the right input,
    4365             :  * and the left input is also not NIL, otherwise the mark output is
    4366             :  * NIL. */
    4367             : gdk_return
    4368       19361 : BATmarkjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4369             :             BUN estimate)
    4370             : {
    4371       19361 :         return leftjoin(r1p, r2p, r3p, l, r, sl, sr, false, true, r2p == NULL,
    4372             :                         false, false, false, false, estimate, __func__,
    4373       19361 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4374             : }
    4375             : 
    4376             : /* Return a candidate list with the list of rows in l whose value also
    4377             :  * occurs in r.  This is just the left output of a semi-join. */
    4378             : BAT *
    4379       10039 : BATintersect(BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, bool max_one,
    4380             :              BUN estimate)
    4381             : {
    4382       10039 :         BAT *bn;
    4383             : 
    4384       10039 :         if (leftjoin(&bn, NULL, NULL, l, r, sl, sr, nil_matches,
    4385             :                      false, true, false, false, max_one, false,
    4386             :                      estimate, __func__,
    4387       10039 :                      GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0) == GDK_SUCCEED)
    4388       10040 :                 return bn;
    4389             :         return NULL;
    4390             : }
    4391             : 
    4392             : /* Return the difference of l and r.  The result is a BAT with the
    4393             :  * oids of those values in l that do not occur in r.  This is what you
    4394             :  * might call an anti-semi-join.  The result is a candidate list. */
    4395             : BAT *
    4396      161379 : BATdiff(BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, bool not_in,
    4397             :         BUN estimate)
    4398             : {
    4399      161379 :         BAT *bn;
    4400             : 
    4401      161379 :         if (leftjoin(&bn, NULL, NULL, l, r, sl, sr, nil_matches,
    4402             :                      false, false, true, not_in, false, false,
    4403             :                      estimate, __func__,
    4404      161379 :                      GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0) == GDK_SUCCEED)
    4405      161244 :                 return bn;
    4406             :         return NULL;
    4407             : }
    4408             : 
    4409             : gdk_return
    4410       50947 : BATthetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, int op, bool nil_matches, BUN estimate)
    4411             : {
    4412       50947 :         int opcode = 0;
    4413       50947 :         lng t0 = 0;
    4414             : 
    4415             :         /* encode operator as a bit mask into opcode */
    4416       50947 :         switch (op) {
    4417           0 :         case JOIN_EQ:
    4418           0 :                 return BATjoin(r1p, r2p, l, r, sl, sr, nil_matches, estimate);
    4419             :         case JOIN_NE:
    4420             :                 opcode = MASK_NE;
    4421             :                 break;
    4422        8404 :         case JOIN_LT:
    4423        8404 :                 opcode = MASK_LT;
    4424        8404 :                 break;
    4425          11 :         case JOIN_LE:
    4426          11 :                 opcode = MASK_LE;
    4427          11 :                 break;
    4428       42431 :         case JOIN_GT:
    4429       42431 :                 opcode = MASK_GT;
    4430       42431 :                 break;
    4431          34 :         case JOIN_GE:
    4432          34 :                 opcode = MASK_GE;
    4433          34 :                 break;
    4434           0 :         default:
    4435           0 :                 GDKerror("unknown operator %d.\n", op);
    4436           0 :                 return GDK_FAIL;
    4437             :         }
    4438             : 
    4439       50947 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4440       50947 :         *r1p = NULL;
    4441       50947 :         if (r2p) {
    4442        8500 :                 *r2p = NULL;
    4443             :         }
    4444       50947 :         if (joinparamcheck(l, r, NULL, sl, sr, __func__) != GDK_SUCCEED)
    4445             :                 return GDK_FAIL;
    4446             : 
    4447       50924 :         return thetajoin(r1p, r2p, l, r, sl, sr, opcode, estimate, nil_matches,
    4448             :                          __func__, t0);
    4449             : }
    4450             : 
    4451             : gdk_return
    4452      414343 : BATjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, BUN estimate)
    4453             : {
    4454      414343 :         struct canditer lci, rci;
    4455      414343 :         bool lhash = false, rhash = false, lcand = false;
    4456      414343 :         bool plhash = false, prhash = false, rcand = false;
    4457      414343 :         bool swap;
    4458      414343 :         bat parent;
    4459      414343 :         double rcost = 0;
    4460      414343 :         double lcost = 0;
    4461      414343 :         gdk_return rc;
    4462      414343 :         lng t0 = 0;
    4463      414343 :         BAT *r2 = NULL;
    4464      414343 :         BAT *lp = NULL;
    4465      414343 :         BAT *rp = NULL;
    4466             : 
    4467      414343 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4468             : 
    4469      414343 :         canditer_init(&lci, l, sl);
    4470      414878 :         canditer_init(&rci, r, sr);
    4471             : 
    4472      414942 :         if ((parent = VIEWtparent(l)) != 0) {
    4473       68827 :                 lp = BATdescriptor(parent);
    4474       68825 :                 if (lp == NULL)
    4475             :                         return GDK_FAIL;
    4476       68825 :                 if (l->hseqbase == lp->hseqbase &&
    4477       68545 :                     BATcount(l) == BATcount(lp) &&
    4478       26149 :                     ATOMtype(l->ttype) == ATOMtype(lp->ttype)) {
    4479             :                         l = lp;
    4480             :                 } else {
    4481       55751 :                         BBPunfix(lp->batCacheid);
    4482       55751 :                         lp = NULL;
    4483             :                 }
    4484             :         }
    4485      414941 :         if ((parent = VIEWtparent(r)) != 0) {
    4486      320922 :                 rp = BATdescriptor(parent);
    4487      320877 :                 if (rp == NULL) {
    4488           0 :                         BBPreclaim(lp);
    4489           0 :                         return GDK_FAIL;
    4490             :                 }
    4491      320877 :                 if (r->hseqbase == rp->hseqbase &&
    4492      544844 :                     BATcount(r) == BATcount(rp) &&
    4493      487790 :                     ATOMtype(r->ttype) == ATOMtype(rp->ttype)) {
    4494             :                         r = rp;
    4495             :                 } else {
    4496       76973 :                         BBPunfix(rp->batCacheid);
    4497       76973 :                         rp = NULL;
    4498             :                 }
    4499             :         }
    4500             : 
    4501      414821 :         if (l->ttype == TYPE_msk || mask_cand(l)) {
    4502           0 :                 l = BATunmask(l);
    4503           0 :                 BBPreclaim(lp);
    4504           0 :                 if (l == NULL) {
    4505           0 :                         BBPreclaim(rp);
    4506           0 :                         return GDK_FAIL;
    4507             :                 }
    4508             :                 lp = l;
    4509             :         }
    4510      414821 :         if (r->ttype == TYPE_msk || mask_cand(r)) {
    4511          24 :                 r = BATunmask(r);
    4512          24 :                 BBPreclaim(rp);
    4513          24 :                 if (r == NULL) {
    4514           0 :                         BBPreclaim(lp);
    4515           0 :                         return GDK_FAIL;
    4516             :                 }
    4517             :                 rp = r;
    4518             :         }
    4519             : 
    4520      414821 :         *r1p = NULL;
    4521      414821 :         if (r2p)
    4522      369739 :                 *r2p = NULL;
    4523             : 
    4524      414821 :         if (joinparamcheck(l, r, NULL, sl, sr, __func__) != GDK_SUCCEED) {
    4525           0 :                 rc = GDK_FAIL;
    4526           0 :                 goto doreturn;
    4527             :         }
    4528             : 
    4529      414673 :         if (lci.ncand == 0 || rci.ncand == 0) {
    4530      334251 :                 TRC_DEBUG(ALGO, "BATjoin(l=" ALGOBATFMT ","
    4531             :                           "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    4532             :                           "sr=" ALGOOPTBATFMT ",nil_matches=%d)\n",
    4533             :                           ALGOBATPAR(l), ALGOBATPAR(r),
    4534             :                           ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    4535             :                           nil_matches);
    4536      334251 :                 rc = nomatch(r1p, r2p, NULL, l, r, &lci,
    4537             :                              0, false, false, __func__, t0);
    4538      333035 :                 goto doreturn;
    4539             :         }
    4540             : 
    4541       80422 :         swap = false;
    4542             : 
    4543       80422 :         if (lci.ncand == 1 || (BATordered(l) && BATordered_rev(l)) || (l->ttype == TYPE_void && is_oid_nil(l->tseqbase))) {
    4544             :                 /* single value to join, use select */
    4545       41066 :                 rc = selectjoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4546             :                                 nil_matches, false, false, false, false,
    4547             :                                 t0, false, __func__);
    4548       40956 :                 goto doreturn;
    4549       39360 :         } else if (rci.ncand == 1 || (BATordered(r) && BATordered_rev(r)) || (r->ttype == TYPE_void && is_oid_nil(r->tseqbase))) {
    4550             :                 /* single value to join, use select */
    4551       13921 :                 rc = selectjoin(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4552             :                                 nil_matches, false, false, false, false,
    4553             :                                 t0, true, __func__);
    4554        9938 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4555        6050 :                         BBPunfix(r2->batCacheid);
    4556        9953 :                 goto doreturn;
    4557       29362 :         } else if (BATtdense(r) && rci.tpe == cand_dense) {
    4558             :                 /* use special implementation for dense right-hand side */
    4559        1654 :                 rc = mergejoin_void(r1p, r2p, NULL, l, r, &lci, &rci,
    4560             :                                     false, false, t0, false, __func__);
    4561        1642 :                 goto doreturn;
    4562       27708 :         } else if (BATtdense(l) && lci.tpe == cand_dense) {
    4563             :                 /* use special implementation for dense right-hand side */
    4564          79 :                 rc = mergejoin_void(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4565             :                                     false, false, t0, true, __func__);
    4566          53 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4567          27 :                         BBPunfix(r2->batCacheid);
    4568          53 :                 goto doreturn;
    4569       42333 :         } else if ((BATordered(l) || BATordered_rev(l)) &&
    4570       19253 :                    (BATordered(r) || BATordered_rev(r))) {
    4571             :                 /* both sorted */
    4572       10177 :                 rc = mergejoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4573             :                                nil_matches, false, false, false, false, false, false,
    4574             :                                estimate, t0, false, __func__);
    4575       10071 :                 goto doreturn;
    4576             :         }
    4577             : 
    4578       17488 :         lcost = joincost(l, rci.ncand, &lci, &lhash, &plhash, &lcand);
    4579       17481 :         rcost = joincost(r, lci.ncand, &rci, &rhash, &prhash, &rcand);
    4580       17449 :         if (lcost < 0 || rcost < 0) {
    4581           0 :                 rc = GDK_FAIL;
    4582           0 :                 goto doreturn;
    4583             :         }
    4584             : 
    4585             :         /* if the cost of doing searches on l is lower than the cost
    4586             :          * of doing searches on r, we swap */
    4587       17449 :         swap = (lcost < rcost);
    4588             : 
    4589       34932 :         if ((r->ttype == TYPE_void && r->tvheap != NULL) ||
    4590       35063 :             ((BATordered(r) || BATordered_rev(r)) &&
    4591        5135 :              (lci.ncand * (log2((double) rci.ncand) + 1) < (swap ? lcost : rcost)))) {
    4592             :                 /* r is sorted and it is cheaper to do multiple binary
    4593             :                  * searches than it is to use a hash */
    4594         343 :                 rc = mergejoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4595             :                                nil_matches, false, false, false, false, false, false,
    4596             :                                estimate, t0, false, __func__);
    4597       34291 :         } else if ((l->ttype == TYPE_void && l->tvheap != NULL) ||
    4598       34501 :             ((BATordered(l) || BATordered_rev(l)) &&
    4599        4500 :              (rci.ncand * (log2((double) lci.ncand) + 1) < (swap ? lcost : rcost)))) {
    4600             :                 /* l is sorted and it is cheaper to do multiple binary
    4601             :                  * searches than it is to use a hash */
    4602        3539 :                 rc = mergejoin(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4603             :                                nil_matches, false, false, false, false, false, false,
    4604             :                                estimate, t0, true, __func__);
    4605        1728 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4606           3 :                         BBPunfix(r2->batCacheid);
    4607       15377 :         } else if (swap) {
    4608       14663 :                 rc = hashjoin(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4609             :                               nil_matches, false, false, false, false, false, false,
    4610             :                               estimate, t0, true, lhash, plhash, lcand,
    4611             :                               __func__);
    4612        7614 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4613         609 :                         BBPunfix(r2->batCacheid);
    4614             :         } else {
    4615        7741 :                 rc = hashjoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4616             :                               nil_matches, false, false, false, false, false, false,
    4617             :                               estimate, t0, false, rhash, prhash, rcand,
    4618             :                               __func__);
    4619             :         }
    4620      413092 :   doreturn:
    4621      413092 :         BBPreclaim(lp);
    4622      412655 :         BBPreclaim(rp);
    4623             :         return rc;
    4624             : }
    4625             : 
    4626             : gdk_return
    4627           0 : BATbandjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4628             :             const void *c1, const void *c2, bool linc, bool hinc, BUN estimate)
    4629             : {
    4630           0 :         lng t0 = 0;
    4631           0 :         struct canditer lci, rci;
    4632           0 :         const char *lvals, *rvals;
    4633           0 :         int t;
    4634           0 :         const void *nil = ATOMnilptr(l->ttype);
    4635           0 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    4636           0 :         const char *vl, *vr;
    4637           0 :         oid lastr = 0;          /* last value inserted into r2 */
    4638           0 :         BUN nr;
    4639           0 :         oid lo, ro;
    4640           0 :         bool lskipped = false;  /* whether we skipped values in l */
    4641             : 
    4642           0 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4643             : 
    4644           0 :         size_t counter = 0;
    4645           0 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4646             : 
    4647             : 
    4648           0 :         MT_thread_setalgorithm(__func__);
    4649           0 :         *r1p = NULL;
    4650           0 :         if (r2p) {
    4651           0 :                 *r2p = NULL;
    4652             :         }
    4653           0 :         if (joinparamcheck(l, r, NULL, sl, sr, __func__) != GDK_SUCCEED)
    4654             :                 return GDK_FAIL;
    4655             : 
    4656           0 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    4657             : 
    4658           0 :         t = ATOMtype(l->ttype);
    4659           0 :         t = ATOMbasetype(t);
    4660             : 
    4661           0 :         canditer_init(&lci, l, sl);
    4662           0 :         canditer_init(&rci, r, sr);
    4663             : 
    4664           0 :         if (lci.ncand == 0 || rci.ncand == 0)
    4665           0 :                 return nomatch(r1p, r2p, NULL, l, r, &lci,
    4666             :                                0, false, false, __func__, t0);
    4667             : 
    4668           0 :         switch (t) {
    4669           0 :         case TYPE_bte:
    4670           0 :                 if (is_bte_nil(*(const bte *)c1) ||
    4671           0 :                     is_bte_nil(*(const bte *)c2) ||
    4672           0 :                     -*(const bte *)c1 > *(const bte *)c2 ||
    4673           0 :                     ((!hinc || !linc) && -*(const bte *)c1 == *(const bte *)c2))
    4674           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4675             :                                        0, false, false, __func__, t0);
    4676             :                 break;
    4677           0 :         case TYPE_sht:
    4678           0 :                 if (is_sht_nil(*(const sht *)c1) ||
    4679           0 :                     is_sht_nil(*(const sht *)c2) ||
    4680           0 :                     -*(const sht *)c1 > *(const sht *)c2 ||
    4681           0 :                     ((!hinc || !linc) && -*(const sht *)c1 == *(const sht *)c2))
    4682           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4683             :                                        0, false, false, __func__, t0);
    4684             :                 break;
    4685           0 :         case TYPE_int:
    4686           0 :                 if (is_int_nil(*(const int *)c1) ||
    4687           0 :                     is_int_nil(*(const int *)c2) ||
    4688           0 :                     -*(const int *)c1 > *(const int *)c2 ||
    4689           0 :                     ((!hinc || !linc) && -*(const int *)c1 == *(const int *)c2))
    4690           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4691             :                                        0, false, false, __func__, t0);
    4692             :                 break;
    4693           0 :         case TYPE_lng:
    4694           0 :                 if (is_lng_nil(*(const lng *)c1) ||
    4695           0 :                     is_lng_nil(*(const lng *)c2) ||
    4696           0 :                     -*(const lng *)c1 > *(const lng *)c2 ||
    4697           0 :                     ((!hinc || !linc) && -*(const lng *)c1 == *(const lng *)c2))
    4698           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4699             :                                        0, false, false, __func__, t0);
    4700             :                 break;
    4701             : #ifdef HAVE_HGE
    4702           0 :         case TYPE_hge:
    4703           0 :                 if (is_hge_nil(*(const hge *)c1) ||
    4704           0 :                     is_hge_nil(*(const hge *)c2) ||
    4705           0 :                     -*(const hge *)c1 > *(const hge *)c2 ||
    4706           0 :                     ((!hinc || !linc) && -*(const hge *)c1 == *(const hge *)c2))
    4707           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4708             :                                        0, false, false, __func__, t0);
    4709             :                 break;
    4710             : #endif
    4711           0 :         case TYPE_flt:
    4712           0 :                 if (is_flt_nil(*(const flt *)c1) ||
    4713           0 :                     is_flt_nil(*(const flt *)c2) ||
    4714           0 :                     -*(const flt *)c1 > *(const flt *)c2 ||
    4715           0 :                     ((!hinc || !linc) && -*(const flt *)c1 == *(const flt *)c2))
    4716           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4717             :                                        0, false, false, __func__, t0);
    4718             :                 break;
    4719           0 :         case TYPE_dbl:
    4720           0 :                 if (is_dbl_nil(*(const dbl *)c1) ||
    4721           0 :                     is_dbl_nil(*(const dbl *)c2) ||
    4722           0 :                     -*(const dbl *)c1 > *(const dbl *)c2 ||
    4723           0 :                     ((!hinc || !linc) && -*(const dbl *)c1 == *(const dbl *)c2))
    4724           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4725             :                                        0, false, false, __func__, t0);
    4726             :                 break;
    4727           0 :         default:
    4728           0 :                 GDKerror("unsupported type\n");
    4729           0 :                 return GDK_FAIL;
    4730             :         }
    4731             : 
    4732           0 :         BUN maxsize = joininitresults(r1p, r2p, NULL, lci.ncand, rci.ncand, false, false,
    4733             :                                       false, false, false, false, estimate);
    4734           0 :         if (maxsize == BUN_NONE)
    4735             :                 return GDK_FAIL;
    4736           0 :         BAT *r1 = *r1p;
    4737           0 :         BAT *r2 = r2p ? *r2p : NULL;
    4738           0 :         BATiter li = bat_iterator(l);
    4739           0 :         BATiter ri = bat_iterator(r);
    4740             : 
    4741           0 :         lvals = (const char *) li.base;
    4742           0 :         rvals = (const char *) ri.base;
    4743           0 :         assert(ri.vh == NULL);
    4744             : 
    4745           0 :         assert(lvals != NULL);
    4746           0 :         assert(rvals != NULL);
    4747             : 
    4748           0 :         r1->tkey = true;
    4749           0 :         r1->tsorted = true;
    4750           0 :         r1->trevsorted = true;
    4751           0 :         if (r2) {
    4752           0 :                 r2->tkey = true;
    4753           0 :                 r2->tsorted = true;
    4754           0 :                 r2->trevsorted = true;
    4755             :         }
    4756             : 
    4757             :         /* nested loop implementation for band join */
    4758           0 :         for (BUN lidx = 0; lidx < lci.ncand; lidx++) {
    4759           0 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    4760             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    4761           0 :                 lo = canditer_next(&lci);
    4762           0 :                 vl = FVALUE(l, lo - l->hseqbase);
    4763           0 :                 if (cmp(vl, nil) == 0)
    4764           0 :                         continue;
    4765           0 :                 nr = 0;
    4766           0 :                 canditer_reset(&rci);
    4767           0 :                 for (BUN ridx = 0; ridx < rci.ncand; ridx++) {
    4768           0 :                         ro = canditer_next(&rci);
    4769           0 :                         vr = FVALUE(r, ro - r->hseqbase);
    4770           0 :                         switch (ATOMtype(li.type)) {
    4771           0 :                         case TYPE_bte: {
    4772           0 :                                 if (is_bte_nil(*(const bte *) vr))
    4773           0 :                                         continue;
    4774           0 :                                 sht v1 = (sht) *(const bte *) vr, v2;
    4775           0 :                                 v2 = v1;
    4776           0 :                                 v1 -= *(const bte *)c1;
    4777           0 :                                 if (*(const bte *)vl <= v1 &&
    4778           0 :                                     (!linc || *(const bte *)vl != v1))
    4779           0 :                                         continue;
    4780           0 :                                 v2 += *(const bte *)c2;
    4781           0 :                                 if (*(const bte *)vl >= v2 &&
    4782           0 :                                     (!hinc || *(const bte *)vl != v2))
    4783           0 :                                         continue;
    4784             :                                 break;
    4785             :                         }
    4786           0 :                         case TYPE_sht: {
    4787           0 :                                 if (is_sht_nil(*(const sht *) vr))
    4788           0 :                                         continue;
    4789           0 :                                 int v1 = (int) *(const sht *) vr, v2;
    4790           0 :                                 v2 = v1;
    4791           0 :                                 v1 -= *(const sht *)c1;
    4792           0 :                                 if (*(const sht *)vl <= v1 &&
    4793           0 :                                     (!linc || *(const sht *)vl != v1))
    4794           0 :                                         continue;
    4795           0 :                                 v2 += *(const sht *)c2;
    4796           0 :                                 if (*(const sht *)vl >= v2 &&
    4797           0 :                                     (!hinc || *(const sht *)vl != v2))
    4798           0 :                                         continue;
    4799             :                                 break;
    4800             :                         }
    4801           0 :                         case TYPE_int: {
    4802           0 :                                 if (is_int_nil(*(const int *) vr))
    4803           0 :                                         continue;
    4804           0 :                                 lng v1 = (lng) *(const int *) vr, v2;
    4805           0 :                                 v2 = v1;
    4806           0 :                                 v1 -= *(const int *)c1;
    4807           0 :                                 if (*(const int *)vl <= v1 &&
    4808           0 :                                     (!linc || *(const int *)vl != v1))
    4809           0 :                                         continue;
    4810           0 :                                 v2 += *(const int *)c2;
    4811           0 :                                 if (*(const int *)vl >= v2 &&
    4812           0 :                                     (!hinc || *(const int *)vl != v2))
    4813           0 :                                         continue;
    4814             :                                 break;
    4815             :                         }
    4816             : #ifdef HAVE_HGE
    4817           0 :                         case TYPE_lng: {
    4818           0 :                                 if (is_lng_nil(*(const lng *) vr))
    4819           0 :                                         continue;
    4820           0 :                                 hge v1 = (hge) *(const lng *) vr, v2;
    4821           0 :                                 v2 = v1;
    4822           0 :                                 v1 -= *(const lng *)c1;
    4823           0 :                                 if (*(const lng *)vl <= v1 &&
    4824           0 :                                     (!linc || *(const lng *)vl != v1))
    4825           0 :                                         continue;
    4826           0 :                                 v2 += *(const lng *)c2;
    4827           0 :                                 if (*(const lng *)vl >= v2 &&
    4828           0 :                                     (!hinc || *(const lng *)vl != v2))
    4829           0 :                                         continue;
    4830             :                                 break;
    4831             :                         }
    4832             : #else
    4833             : #ifdef HAVE___INT128
    4834             :                         case TYPE_lng: {
    4835             :                                 if (is_lng_nil(*(const lng *) vr))
    4836             :                                         continue;
    4837             :                                 __int128 v1 = (__int128) *(const lng *) vr, v2;
    4838             :                                 v2 = v1;
    4839             :                                 v1 -= *(const lng *)c1;
    4840             :                                 if (*(const lng *)vl <= v1 &&
    4841             :                                     (!linc || *(const lng *)vl != v1))
    4842             :                                         continue;
    4843             :                                 v2 += *(const lng *)c2;
    4844             :                                 if (*(const lng *)vl >= v2 &&
    4845             :                                     (!hinc || *(const lng *)vl != v2))
    4846             :                                         continue;
    4847             :                                 break;
    4848             :                         }
    4849             : #else
    4850             : #ifdef HAVE___INT128_T
    4851             :                         case TYPE_lng: {
    4852             :                                 if (is_lng_nil(*(const lng *) vr))
    4853             :                                         continue;
    4854             :                                 __int128_t v1 = (__int128_t) *(const lng *) vr, v2;
    4855             :                                 v2 = v1;
    4856             :                                 v1 -= *(const lng *)c1;
    4857             :                                 if (*(const lng *)vl <= v1 &&
    4858             :                                     (!linc || *(const lng *)vl != v1))
    4859             :                                         continue;
    4860             :                                 v2 += *(const lng *)c2;
    4861             :                                 if (*(const lng *)vl >= v2 &&
    4862             :                                     (!hinc || *(const lng *)vl != v2))
    4863             :                                         continue;
    4864             :                                 break;
    4865             :                         }
    4866             : #else
    4867             :                         case TYPE_lng: {
    4868             :                                 if (is_lng_nil(*(const lng *) vr))
    4869             :                                         continue;
    4870             :                                 lng v1, v2;
    4871             :                                 SUBI_WITH_CHECK(*(const lng *)vr,
    4872             :                                                *(const lng *)c1,
    4873             :                                                lng, v1,
    4874             :                                                GDK_lng_max,
    4875             :                                                do{if(*(const lng*)c1<0)goto nolmatch;else goto lmatch1;}while(false));
    4876             :                                 if (*(const lng *)vl <= v1 &&
    4877             :                                     (!linc || *(const lng *)vl != v1))
    4878             :                                         continue;
    4879             :                                   lmatch1:
    4880             :                                 ADDI_WITH_CHECK(*(const lng *)vr,
    4881             :                                                *(const lng *)c2,
    4882             :                                                lng, v2,
    4883             :                                                GDK_lng_max,
    4884             :                                                do{if(*(const lng*)c2>0)goto nolmatch;else goto lmatch2;}while(false));
    4885             :                                 if (*(const lng *)vl >= v2 &&
    4886             :                                     (!hinc || *(const lng *)vl != v2))
    4887             :                                         continue;
    4888             :                                   lmatch2:
    4889             :                                 break;
    4890             :                                   nolmatch:
    4891             :                                 continue;
    4892             :                         }
    4893             : #endif
    4894             : #endif
    4895             : #endif
    4896             : #ifdef HAVE_HGE
    4897           0 :                         case TYPE_hge: {
    4898           0 :                                 if (is_hge_nil(*(const hge *) vr))
    4899           0 :                                         continue;
    4900           0 :                                 hge v1, v2;
    4901           0 :                                 SUBI_WITH_CHECK(*(const hge *)vr,
    4902             :                                                *(const hge *)c1,
    4903             :                                                hge, v1,
    4904             :                                                GDK_hge_max,
    4905             :                                                do{if(*(const hge*)c1<0)goto nohmatch;else goto hmatch1;}while(false));
    4906           0 :                                 if (*(const hge *)vl <= v1 &&
    4907           0 :                                     (!linc || *(const hge *)vl != v1))
    4908           0 :                                         continue;
    4909           0 :                                   hmatch1:
    4910           0 :                                 ADDI_WITH_CHECK(*(const hge *)vr,
    4911             :                                                *(const hge *)c2,
    4912             :                                                hge, v2,
    4913             :                                                GDK_hge_max,
    4914             :                                                do{if(*(const hge*)c2>0)goto nohmatch;else goto hmatch2;}while(false));
    4915           0 :                                 if (*(const hge *)vl >= v2 &&
    4916           0 :                                     (!hinc || *(const hge *)vl != v2))
    4917           0 :                                         continue;
    4918           0 :                                   hmatch2:
    4919             :                                 break;
    4920           0 :                                   nohmatch:
    4921           0 :                                 continue;
    4922             :                         }
    4923             : #endif
    4924           0 :                         case TYPE_flt: {
    4925           0 :                                 if (is_flt_nil(*(const flt *) vr))
    4926           0 :                                         continue;
    4927           0 :                                 dbl v1 = (dbl) *(const flt *) vr, v2;
    4928           0 :                                 v2 = v1;
    4929           0 :                                 v1 -= *(const flt *)c1;
    4930           0 :                                 if (*(const flt *)vl <= v1 &&
    4931           0 :                                     (!linc || *(const flt *)vl != v1))
    4932           0 :                                         continue;
    4933           0 :                                 v2 += *(const flt *)c2;
    4934           0 :                                 if (*(const flt *)vl >= v2 &&
    4935           0 :                                     (!hinc || *(const flt *)vl != v2))
    4936           0 :                                         continue;
    4937             :                                 break;
    4938             :                         }
    4939           0 :                         case TYPE_dbl: {
    4940           0 :                                 if (is_dbl_nil(*(const dbl *) vr))
    4941           0 :                                         continue;
    4942           0 :                                 dbl v1, v2;
    4943           0 :                                 SUBF_WITH_CHECK(*(const dbl *)vr,
    4944             :                                                *(const dbl *)c1,
    4945             :                                                dbl, v1,
    4946             :                                                GDK_dbl_max,
    4947             :                                                do{if(*(const dbl*)c1<0)goto nodmatch;else goto dmatch1;}while(false));
    4948           0 :                                 if (*(const dbl *)vl <= v1 &&
    4949           0 :                                     (!linc || *(const dbl *)vl != v1))
    4950           0 :                                         continue;
    4951           0 :                                   dmatch1:
    4952           0 :                                 ADDF_WITH_CHECK(*(const dbl *)vr,
    4953             :                                                *(const dbl *)c2,
    4954             :                                                dbl, v2,
    4955             :                                                GDK_dbl_max,
    4956             :                                                do{if(*(const dbl*)c2>0)goto nodmatch;else goto dmatch2;}while(false));
    4957           0 :                                 if (*(const dbl *)vl >= v2 &&
    4958           0 :                                     (!hinc || *(const dbl *)vl != v2))
    4959           0 :                                         continue;
    4960           0 :                                   dmatch2:
    4961             :                                 break;
    4962           0 :                                   nodmatch:
    4963           0 :                                 continue;
    4964             :                         }
    4965             :                         }
    4966           0 :                         if (maybeextend(r1, r2, NULL, 1, lci.next, lci.ncand, maxsize) != GDK_SUCCEED)
    4967           0 :                                 goto bailout;
    4968           0 :                         if (BATcount(r1) > 0) {
    4969           0 :                                 if (r2 && lastr + 1 != ro)
    4970           0 :                                         r2->tseqbase = oid_nil;
    4971           0 :                                 if (nr == 0) {
    4972           0 :                                         r1->trevsorted = false;
    4973           0 :                                         if (r2 == NULL) {
    4974             :                                                 /* nothing */
    4975           0 :                                         } else if (lastr > ro) {
    4976           0 :                                                 r2->tsorted = false;
    4977           0 :                                                 r2->tkey = false;
    4978           0 :                                         } else if (lastr < ro) {
    4979           0 :                                                 r2->trevsorted = false;
    4980             :                                         } else {
    4981           0 :                                                 r2->tkey = false;
    4982             :                                         }
    4983             :                                 }
    4984             :                         }
    4985           0 :                         APPEND(r1, lo);
    4986           0 :                         if (r2) {
    4987           0 :                                 APPEND(r2, ro);
    4988             :                         }
    4989           0 :                         lastr = ro;
    4990           0 :                         nr++;
    4991             :                 }
    4992           0 :                 if (nr > 1) {
    4993           0 :                         r1->tkey = false;
    4994           0 :                         r1->tseqbase = oid_nil;
    4995           0 :                         if (r2) {
    4996           0 :                                 r2->trevsorted = false;
    4997             :                         }
    4998           0 :                 } else if (nr == 0) {
    4999           0 :                         lskipped = BATcount(r1) > 0;
    5000           0 :                 } else if (lskipped) {
    5001           0 :                         r1->tseqbase = oid_nil;
    5002             :                 }
    5003             :         }
    5004             :         /* also set other bits of heap to correct value to indicate size */
    5005           0 :         BATsetcount(r1, BATcount(r1));
    5006           0 :         if (r2) {
    5007           0 :                 BATsetcount(r2, BATcount(r2));
    5008           0 :                 assert(BATcount(r1) == BATcount(r2));
    5009             :         }
    5010           0 :         if (BATcount(r1) > 0) {
    5011           0 :                 if (BATtdense(r1))
    5012           0 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    5013           0 :                 if (r2 && BATtdense(r2))
    5014           0 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    5015             :         } else {
    5016           0 :                 r1->tseqbase = 0;
    5017           0 :                 if (r2) {
    5018           0 :                         r2->tseqbase = 0;
    5019             :                 }
    5020             :         }
    5021           0 :         bat_iterator_end(&li);
    5022           0 :         bat_iterator_end(&ri);
    5023           0 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT
    5024             :                   ",sl=" ALGOOPTBATFMT "," "sr=" ALGOOPTBATFMT ","
    5025             :                   " -> " ALGOBATFMT "," ALGOOPTBATFMT
    5026             :                   " (" LLFMT "usec)\n",
    5027             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    5028             :                   ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    5029             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    5030             :                   GDKusec() - t0);
    5031             :         return GDK_SUCCEED;
    5032             : 
    5033           0 :   bailout:
    5034           0 :         bat_iterator_end(&li);
    5035           0 :         bat_iterator_end(&ri);
    5036           0 :         BBPreclaim(r1);
    5037           0 :         BBPreclaim(r2);
    5038             :         return GDK_FAIL;
    5039             : }
    5040             : 
    5041             : #define LTany(a,b)      ((*cmp)(a, b) < 0)
    5042             : #define EQany(a,b)      ((*cmp)(a, b) == 0)
    5043             : #define is_any_nil(v)   ((v) == NULL || (*cmp)((v), nil) == 0)
    5044             : 
    5045             : #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)))
    5046             : #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)))
    5047             : #define or3(a,b)        ((a) == 1 || (b) == 1 ? 1 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 0)
    5048             : #define and3(a,b)       ((a) == 0 || (b) == 0 ? 0 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 1)
    5049             : #define not3(a)         (is_bit_nil(a) ? bit_nil : !(a))
    5050             : 
    5051             : #define between3(v, lo, linc, hi, hinc, TYPE)                           \
    5052             :         and3(grtr3(v, lo, linc, TYPE), less3(v, hi, hinc, TYPE))
    5053             : 
    5054             : #define BETWEEN(v, lo, linc, hi, hinc, TYPE)                            \
    5055             :         (is_##TYPE##_nil(v)                                             \
    5056             :          ? bit_nil                                                      \
    5057             :          : (bit) (anti                                                  \
    5058             :                   ? (symmetric                                          \
    5059             :                      ? not3(or3(between3(v, lo, linc, hi, hinc, TYPE),  \
    5060             :                                 between3(v, hi, hinc, lo, linc, TYPE))) \
    5061             :                      : not3(between3(v, lo, linc, hi, hinc, TYPE)))     \
    5062             :                   : (symmetric                                          \
    5063             :                      ? or3(between3(v, lo, linc, hi, hinc, TYPE),       \
    5064             :                            between3(v, hi, hinc, lo, linc, TYPE))       \
    5065             :                      : between3(v, lo, linc, hi, hinc, TYPE))))
    5066             : 
    5067             : static gdk_return
    5068         120 : rangejoin(BAT *r1, BAT *r2, BAT *l, BAT *rl, BAT *rh,
    5069             :           struct canditer *lci, struct canditer *rci,
    5070             :           bool linc, bool hinc, bool anti, bool symmetric, BUN maxsize)
    5071             : {
    5072         120 :         if (!anti && !symmetric) {
    5073             :                 /* we'll need these */
    5074         109 :                 (void) BATordered(l);
    5075         114 :                 (void) BATordered_rev(l);
    5076             :         }
    5077         125 :         BATiter li = bat_iterator(l);
    5078         125 :         BATiter rli = bat_iterator(rl);
    5079         125 :         BATiter rhi = bat_iterator(rh);
    5080         125 :         const char *rlvals, *rhvals;
    5081         125 :         const char *lvars, *rlvars, *rhvars;
    5082         125 :         const void *nil = ATOMnilptr(li.type);
    5083         125 :         int (*cmp)(const void *, const void *) = ATOMcompare(li.type);
    5084         125 :         int t;
    5085         125 :         BUN cnt, ncnt, lncand = lci->ncand, rncand = rci->ncand;
    5086         125 :         oid *restrict dst1, *restrict dst2;
    5087         125 :         const void *vrl, *vrh;
    5088         125 :         oid ro;
    5089         125 :         oid rlval = oid_nil, rhval = oid_nil;
    5090         125 :         int sorted = 0;         /* which output column is sorted */
    5091         125 :         Heap *oidxh = NULL;
    5092             : 
    5093         125 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    5094             : 
    5095         375 :         assert(ATOMtype(li.type) == ATOMtype(rli.type));
    5096         250 :         assert(ATOMtype(li.type) == ATOMtype(rhi.type));
    5097         125 :         assert(BATcount(rl) == BATcount(rh));
    5098         125 :         assert(rl->hseqbase == rh->hseqbase);
    5099         125 :         assert(r1->ttype == TYPE_oid);
    5100         125 :         assert(r2 == NULL || r2->ttype == TYPE_oid);
    5101         106 :         assert(r2 == NULL || BATcount(r1) == BATcount(r2));
    5102         125 :         assert(li.type != TYPE_void || !is_oid_nil(l->tseqbase));
    5103         125 :         assert(rli.type != TYPE_void || !is_oid_nil(rl->tseqbase));
    5104         125 :         assert(rhi.type != TYPE_void || !is_oid_nil(rh->tseqbase));
    5105             : 
    5106         125 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
    5107             :                   "rl=" ALGOBATFMT ",rh=" ALGOBATFMT ","
    5108             :                   "sl=" ALGOOPTBATFMT ",sr=" ALGOOPTBATFMT ","
    5109             :                   "anti=%s,symmetric=%s\n",
    5110             :                   ALGOBATPAR(l),
    5111             :                   ALGOBATPAR(rl),
    5112             :                   ALGOBATPAR(rh),
    5113             :                   ALGOOPTBATPAR(lci->s),
    5114             :                   ALGOOPTBATPAR(rci->s),
    5115             :                   anti ? "true" : "false",
    5116             :                   symmetric ? "true" : "false");
    5117             : 
    5118         125 :         rlvals = rli.type == TYPE_void ? NULL : (const char *) rli.base;
    5119         125 :         rhvals = rhi.type == TYPE_void ? NULL : (const char *) rhi.base;
    5120         125 :         dst1 = (oid *) Tloc(r1, 0);
    5121         125 :         dst2 = r2 ? (oid *) Tloc(r2, 0) : NULL;
    5122             : 
    5123         125 :         t = ATOMtype(li.type);
    5124         125 :         t = ATOMbasetype(t);
    5125             : 
    5126         125 :         if (li.vh && li.type) {
    5127          17 :                 assert(rli.vh && rli.type);
    5128          17 :                 assert(rhi.vh && rhi.type);
    5129          17 :                 lvars = li.vh->base;
    5130          17 :                 rlvars = rli.vh->base;
    5131          17 :                 rhvars = rhi.vh->base;
    5132             :         } else {
    5133         108 :                 assert(rli.vh == NULL);
    5134         108 :                 assert(rhi.vh == NULL);
    5135             :                 lvars = rlvars = rhvars = NULL;
    5136             :         }
    5137             : 
    5138         125 :         if (!anti && !symmetric && !li.sorted && !li.revsorted) {
    5139          13 :                 (void) BATcheckorderidx(l);
    5140          13 :                 MT_lock_set(&l->batIdxLock);
    5141          13 :                 if ((oidxh = l->torderidx) != NULL)
    5142           0 :                         HEAPincref(oidxh);
    5143          13 :                 MT_lock_unset(&l->batIdxLock);
    5144             : #if 0 /* needs checking */
    5145             :                 if (oidxh == NULL && VIEWtparent(l)) {
    5146             : /* if enabled, need to fix/unfix parent bat */
    5147             :                         BAT *pb = BBP_desc(VIEWtparent(l));
    5148             :                         (void) BATcheckorderidx(pb);
    5149             :                         MT_lock_set(&pb->batIdxLock);
    5150             :                         if ((oidxh = pb->torderidx) != NULL) {
    5151             :                                 HEAPincref(oidxh);
    5152             :                                 l = pb;
    5153             :                         }
    5154             :                         MT_lock_unset(&pb->batIdxLock);
    5155             :                 }
    5156             : #endif
    5157             :         }
    5158             : 
    5159         125 :         vrl = &rlval;
    5160         125 :         vrh = &rhval;
    5161         125 :         if (!anti && !symmetric && (li.sorted || li.revsorted || oidxh)) {
    5162             :                 /* left column is sorted, use binary search */
    5163         101 :                 sorted = 2;
    5164         613 :                 TIMEOUT_LOOP(rncand, qry_ctx) {
    5165         411 :                         BUN low, high;
    5166             : 
    5167         411 :                         ro = canditer_next(rci);
    5168         397 :                         if (rlvals) {
    5169         397 :                                 vrl = VALUE(rl, ro - rl->hseqbase);
    5170             :                         } else {
    5171             :                                 /* TYPE_void */
    5172           0 :                                 rlval = ro - rl->hseqbase + rl->tseqbase;
    5173             :                         }
    5174         397 :                         if (rhvals) {
    5175         397 :                                 vrh = VALUE(rh, ro - rh->hseqbase);
    5176             :                         } else {
    5177             :                                 /* TYPE_void */
    5178           0 :                                 rhval = ro - rh->hseqbase + rh->tseqbase;
    5179             :                         }
    5180         397 :                         if (cmp(vrl, nil) == 0 || cmp(vrh, nil) == 0)
    5181           9 :                                 continue;
    5182         384 :                         if (li.sorted) {
    5183         381 :                                 if (linc)
    5184         271 :                                         low = SORTfndfirst(l, vrl);
    5185             :                                 else
    5186         110 :                                         low = SORTfndlast(l, vrl);
    5187         408 :                                 if (hinc)
    5188         349 :                                         high = SORTfndlast(l, vrh);
    5189             :                                 else
    5190          59 :                                         high = SORTfndfirst(l, vrh);
    5191           3 :                         } else  if (li.revsorted) {
    5192           3 :                                 if (hinc)
    5193           3 :                                         low = SORTfndfirst(l, vrh);
    5194             :                                 else
    5195           0 :                                         low = SORTfndlast(l, vrh);
    5196           3 :                                 if (linc)
    5197           3 :                                         high = SORTfndlast(l, vrl);
    5198             :                                 else
    5199           0 :                                         high = SORTfndfirst(l, vrl);
    5200             :                         } else {
    5201           0 :                                 assert(oidxh);
    5202           0 :                                 if (linc)
    5203           0 :                                         low = ORDERfndfirst(l, oidxh, vrl);
    5204             :                                 else
    5205           0 :                                         low = ORDERfndlast(l, oidxh, vrl);
    5206           0 :                                 if (hinc)
    5207           0 :                                         high = ORDERfndlast(l, oidxh, vrh);
    5208             :                                 else
    5209           0 :                                         high = ORDERfndfirst(l, oidxh, vrh);
    5210             :                         }
    5211         406 :                         if (high <= low)
    5212         224 :                                 continue;
    5213         182 :                         if (li.sorted || li.revsorted) {
    5214         182 :                                 low = canditer_search(lci, low + l->hseqbase, true);
    5215         182 :                                 high = canditer_search(lci, high + l->hseqbase, true);
    5216         182 :                                 assert(high >= low);
    5217             : 
    5218         182 :                                 if (BATcapacity(r1) < BATcount(r1) + high - low) {
    5219           0 :                                         cnt = BATcount(r1) + high - low + 1024;
    5220           0 :                                         if (cnt > maxsize)
    5221             :                                                 cnt = maxsize;
    5222           0 :                                         BATsetcount(r1, BATcount(r1));
    5223           0 :                                         if (BATextend(r1, cnt) != GDK_SUCCEED)
    5224           0 :                                                 goto bailout;
    5225           0 :                                         dst1 = (oid *) Tloc(r1, 0);
    5226           0 :                                         if (r2) {
    5227           0 :                                                 BATsetcount(r2, BATcount(r2));
    5228           0 :                                                 if (BATextend(r2, cnt) != GDK_SUCCEED)
    5229           0 :                                                         goto bailout;
    5230           0 :                                                 assert(BATcapacity(r1) == BATcapacity(r2));
    5231           0 :                                                 dst2 = (oid *) Tloc(r2, 0);
    5232             :                                         }
    5233             :                                 }
    5234         182 :                                 canditer_setidx(lci, low);
    5235         921 :                                 while (low < high) {
    5236         739 :                                         dst1[r1->batCount++] = canditer_next(lci);
    5237         739 :                                         if (r2) {
    5238         727 :                                                 dst2[r2->batCount++] = ro;
    5239             :                                         }
    5240         739 :                                         low++;
    5241             :                                 }
    5242             :                         } else {
    5243           0 :                                 const oid *ord;
    5244             : 
    5245           0 :                                 assert(oidxh);
    5246           0 :                                 ord = (const oid *) oidxh->base + ORDERIDXOFF;
    5247             : 
    5248           0 :                                 if (BATcapacity(r1) < BATcount(r1) + high - low) {
    5249           0 :                                         cnt = BATcount(r1) + high - low + 1024;
    5250           0 :                                         if (cnt > maxsize)
    5251             :                                                 cnt = maxsize;
    5252           0 :                                         BATsetcount(r1, BATcount(r1));
    5253           0 :                                         if (BATextend(r1, cnt) != GDK_SUCCEED)
    5254           0 :                                                 goto bailout;
    5255           0 :                                         dst1 = (oid *) Tloc(r1, 0);
    5256           0 :                                         if (r2) {
    5257           0 :                                                 BATsetcount(r2, BATcount(r2));
    5258           0 :                                                 if (BATextend(r2, cnt) != GDK_SUCCEED)
    5259           0 :                                                         goto bailout;
    5260           0 :                                                 assert(BATcapacity(r1) == BATcapacity(r2));
    5261           0 :                                                 dst2 = (oid *) Tloc(r2, 0);
    5262             :                                         }
    5263             :                                 }
    5264             : 
    5265           0 :                                 while (low < high) {
    5266           0 :                                         if (canditer_contains(lci, ord[low])) {
    5267           0 :                                                 dst1[r1->batCount++] = ord[low];
    5268           0 :                                                 if (r2) {
    5269           0 :                                                         dst2[r2->batCount++] = ro;
    5270             :                                                 }
    5271             :                                         }
    5272           0 :                                         low++;
    5273             :                                 }
    5274             :                         }
    5275             :                 }
    5276         101 :                 if (oidxh)
    5277           0 :                         HEAPdecref(oidxh, false);
    5278         101 :                 TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    5279         101 :                 cnt = BATcount(r1);
    5280         101 :                 assert(r2 == NULL || BATcount(r1) == BATcount(r2));
    5281             :         } else {
    5282             :                 /* nested loop implementation */
    5283          24 :                 const void *vl;
    5284          24 :                 const char *lvals;
    5285          24 :                 oid lval;
    5286             : 
    5287          24 :                 sorted = 1;
    5288          24 :                 lvals = li.type == TYPE_void ? NULL : (const char *) li.base;
    5289          24 :                 vl = &lval;
    5290         281 :                 TIMEOUT_LOOP(lncand, qry_ctx) {
    5291         237 :                         oid lo;
    5292             : 
    5293         237 :                         lo = canditer_next(lci);
    5294         238 :                         if (lvals) {
    5295         238 :                                 vl = VALUE(l, lo - l->hseqbase);
    5296         238 :                                 if (cmp(vl, nil) == 0)
    5297           8 :                                         continue;
    5298             :                         } else {
    5299           0 :                                 lval = lo - l->hseqbase + l->tseqbase;
    5300             :                         }
    5301         230 :                         canditer_reset(rci);
    5302       30864 :                         for (BUN j = 0; j < rncand; j++) {
    5303       30636 :                                 ro = canditer_next(rci);
    5304       23079 :                                 if (rlvals) {
    5305       23079 :                                         vrl = VALUE(rl, ro - rl->hseqbase);
    5306             :                                 } else {
    5307             :                                         /* TYPE_void */
    5308           0 :                                         rlval = ro - rl->hseqbase + rl->tseqbase;
    5309             :                                 }
    5310       23079 :                                 if (rhvals) {
    5311       23079 :                                         vrh = VALUE(rh, ro - rh->hseqbase);
    5312             :                                 } else {
    5313             :                                         /* TYPE_void */
    5314           0 :                                         rhval = ro - rh->hseqbase + rh->tseqbase;
    5315             :                                 }
    5316       23081 :                                 if (BETWEEN(vl, vrl, linc, vrh, hinc, any) != 1)
    5317       18482 :                                         continue;
    5318       12152 :                                 if (BATcount(r1) == BATcapacity(r1)) {
    5319           2 :                                         BUN newcap = BATgrows(r1);
    5320           2 :                                         if (newcap > maxsize)
    5321             :                                                 newcap = maxsize;
    5322           2 :                                         BATsetcount(r1, BATcount(r1));
    5323           2 :                                         if (BATextend(r1, newcap) != GDK_SUCCEED)
    5324           0 :                                                 goto bailout;
    5325           2 :                                         dst1 = (oid *) Tloc(r1, 0);
    5326           2 :                                         if (r2) {
    5327           2 :                                                 BATsetcount(r2, BATcount(r2));
    5328           2 :                                                 if (BATextend(r2, newcap) != GDK_SUCCEED)
    5329           0 :                                                         goto bailout;
    5330           2 :                                                 assert(BATcapacity(r1) == BATcapacity(r2));
    5331           2 :                                                 dst2 = (oid *) Tloc(r2, 0);
    5332             :                                         }
    5333             :                                 }
    5334       12152 :                                 dst1[r1->batCount++] = lo;
    5335       12152 :                                 if (r2) {
    5336       12143 :                                         dst2[r2->batCount++] = ro;
    5337             :                                 }
    5338             :                         }
    5339             :                 }
    5340          21 :                 TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    5341          22 :                 cnt = BATcount(r1);
    5342          22 :                 assert(r2 == NULL || BATcount(r1) == BATcount(r2));
    5343             :         }
    5344             : 
    5345             :         /* also set other bits of heap to correct value to indicate size */
    5346         123 :         BATsetcount(r1, cnt);
    5347             : 
    5348             :         /* set properties using an extra scan (usually not complete) */
    5349         123 :         dst1 = (oid *) Tloc(r1, 0);
    5350         123 :         r1->tkey = true;
    5351         123 :         r1->tsorted = true;
    5352         123 :         r1->trevsorted = true;
    5353         123 :         r1->tseqbase = 0;
    5354         123 :         r1->tnil = false;
    5355         123 :         r1->tnonil = true;
    5356         598 :         for (ncnt = 1; ncnt < cnt; ncnt++) {
    5357         486 :                 if (dst1[ncnt - 1] == dst1[ncnt]) {
    5358         424 :                         r1->tseqbase = oid_nil;
    5359         424 :                         r1->tkey = false;
    5360          62 :                 } else if (dst1[ncnt - 1] < dst1[ncnt]) {
    5361          59 :                         r1->trevsorted = false;
    5362          59 :                         if (dst1[ncnt - 1] + 1 != dst1[ncnt])
    5363           3 :                                 r1->tseqbase = oid_nil;
    5364             :                 } else {
    5365           3 :                         assert(sorted != 1);
    5366           3 :                         r1->tsorted = false;
    5367           3 :                         r1->tseqbase = oid_nil;
    5368           3 :                         r1->tkey = false;
    5369             :                 }
    5370         534 :                 if (!(r1->trevsorted | BATtdense(r1) | r1->tkey | ((sorted != 1) & r1->tsorted)))
    5371             :                         break;
    5372             :         }
    5373         123 :         if (BATtdense(r1))
    5374         102 :                 r1->tseqbase = cnt > 0 ? dst1[0] : 0;
    5375         123 :         if (r2) {
    5376         104 :                 BATsetcount(r2, cnt);
    5377         104 :                 dst2 = (oid *) Tloc(r2, 0);
    5378         104 :                 r2->tkey = true;
    5379         104 :                 r2->tsorted = true;
    5380         104 :                 r2->trevsorted = true;
    5381         104 :                 r2->tseqbase = 0;
    5382         104 :                 r2->tnil = false;
    5383         104 :                 r2->tnonil = true;
    5384         574 :                 for (ncnt = 1; ncnt < cnt; ncnt++) {
    5385         483 :                         if (dst2[ncnt - 1] == dst2[ncnt]) {
    5386          43 :                                 r2->tseqbase = oid_nil;
    5387          43 :                                 r2->tkey = false;
    5388         440 :                         } else if (dst2[ncnt - 1] < dst2[ncnt]) {
    5389         430 :                                 r2->trevsorted = false;
    5390         430 :                                 if (dst2[ncnt - 1] + 1 != dst2[ncnt])
    5391         127 :                                         r2->tseqbase = oid_nil;
    5392             :                         } else {
    5393          10 :                                 assert(sorted != 2);
    5394          10 :                                 r2->tsorted = false;
    5395          10 :                                 r2->tseqbase = oid_nil;
    5396          10 :                                 r2->tkey = false;
    5397             :                         }
    5398         654 :                         if (!(r2->trevsorted | BATtdense(r2) | r2->tkey | ((sorted != 2) & r2->tsorted)))
    5399             :                                 break;
    5400             :                 }
    5401         104 :                 if (BATtdense(r2))
    5402          76 :                         r2->tseqbase = cnt > 0 ? dst2[0] : 0;
    5403             :         }
    5404         123 :         TRC_DEBUG(ALGO, "l=%s,rl=%s,rh=%s -> "
    5405             :                   "(" ALGOBATFMT "," ALGOOPTBATFMT ")\n",
    5406             :                   BATgetId(l), BATgetId(rl), BATgetId(rh),
    5407             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2));
    5408         123 :         bat_iterator_end(&li);
    5409         125 :         bat_iterator_end(&rli);
    5410         124 :         bat_iterator_end(&rhi);
    5411         124 :         return GDK_SUCCEED;
    5412             : 
    5413           0 :   bailout:
    5414           0 :         bat_iterator_end(&li);
    5415           0 :         bat_iterator_end(&rli);
    5416           0 :         bat_iterator_end(&rhi);
    5417           0 :         BBPreclaim(r1);
    5418           0 :         BBPreclaim(r2);
    5419             :         return GDK_FAIL;
    5420             : }
    5421             : 
    5422             : gdk_return
    5423         147 : BATrangejoin(BAT **r1p, BAT **r2p, BAT *l, BAT *rl, BAT *rh,
    5424             :              BAT *sl, BAT *sr, bool linc, bool hinc, bool anti, bool symmetric,
    5425             :              BUN estimate)
    5426             : {
    5427         147 :         struct canditer lci, rci;
    5428         147 :         BAT *r1 = NULL, *r2 = NULL;
    5429         147 :         BUN maxsize;
    5430         147 :         lng t0 = 0;
    5431             : 
    5432         147 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    5433         147 :         *r1p = NULL;
    5434         147 :         if (r2p) {
    5435         122 :                 *r2p = NULL;
    5436             :         }
    5437         147 :         if (joinparamcheck(l, rl, rh, sl, sr, __func__) != GDK_SUCCEED)
    5438             :                 return GDK_FAIL;
    5439         147 :         canditer_init(&lci, l, sl);
    5440         147 :         canditer_init(&rci, rl, sr);
    5441         147 :         if (lci.ncand == 0 ||
    5442         137 :             rci.ncand == 0 ||
    5443         125 :             (l->ttype == TYPE_void && is_oid_nil(l->tseqbase)) ||
    5444         125 :             ((rl->ttype == TYPE_void && is_oid_nil(rl->tseqbase)) &&
    5445           0 :              (rh->ttype == TYPE_void && is_oid_nil(rh->tseqbase)))) {
    5446             :                 /* trivial: empty input */
    5447          22 :                 return nomatch(r1p, r2p, NULL, l, rl, &lci, 0, false, false,
    5448             :                                __func__, t0);
    5449             :         }
    5450         125 :         if (rl->ttype == TYPE_void && is_oid_nil(rl->tseqbase)) {
    5451           0 :                 if (!anti)
    5452           0 :                         return nomatch(r1p, r2p, NULL, l, rl, &lci, 0, false, false,
    5453             :                                        __func__, t0);
    5454           0 :                 return thetajoin(r1p, r2p, l, rh, sl, sr, MASK_GT, estimate, false,
    5455             :                                  __func__, t0);
    5456             :         }
    5457         125 :         if (rh->ttype == TYPE_void && is_oid_nil(rh->tseqbase)) {
    5458           0 :                 if (!anti)
    5459           0 :                         return nomatch(r1p, r2p, NULL, l, rl, &lci, 0, false, false,
    5460             :                                        __func__, t0);
    5461           0 :                 return thetajoin(r1p, r2p, l, rl, sl, sr, MASK_LT, estimate, false,
    5462             :                                  __func__, t0);
    5463             :         }
    5464             : 
    5465         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)
    5466             :                 return GDK_FAIL;
    5467         124 :         *r1p = r1;
    5468         124 :         if (r2p) {
    5469         106 :                 *r2p = r2;
    5470             :         }
    5471         124 :         if (maxsize == 0)
    5472             :                 return GDK_SUCCEED;
    5473             : 
    5474         124 :         return rangejoin(r1, r2, l, rl, rh, &lci, &rci, linc, hinc, anti, symmetric, maxsize);
    5475             : }

Generated by: LCOV version 1.14