Changeset: 1fc7bfdb2ca7 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=1fc7bfdb2ca7
Modified Files:
        gdk/gdk.h
        gdk/gdk_join.c
Branch: default
Log Message:

Implemented BATsubjoin and BATproject.
BATproject is basically the old BATleftfetchjoin.


diffs (192 lines):

diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -3189,6 +3189,8 @@ gdk_export BAT *BATcross(BAT *l, BAT *r)
 gdk_export gdk_return BATsubleftjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT 
*sl, BAT *sr, BUN estimate);
 gdk_export gdk_return BATsubouterjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, 
BAT *sl, BAT *sr, BUN estimate);
 gdk_export gdk_return BATsubthetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, 
BAT *sl, BAT *sr, const char *op, BUN estimate);
+gdk_export gdk_return BATsubjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT 
*sl, BAT *sr, BUN estimate);
+gdk_export BAT *BATproject(BAT *l, BAT *r);
 
 gdk_export BAT *BATslice(BAT *b, BUN low, BUN high);
 gdk_export BAT *BATfetch(BAT *b, BAT *s);
diff --git a/gdk/gdk_join.c b/gdk/gdk_join.c
--- a/gdk/gdk_join.c
+++ b/gdk/gdk_join.c
@@ -852,9 +852,9 @@ thetajoin(BAT *r1, BAT *r2, BAT *l, BAT 
                        if (cmp(vr, nil) == 0)
                                continue;
                        c = cmp(vl, vr);
-                       if (!((c < 0 && opcode & MASK_LT) ||
-                             (c > 0 && opcode & MASK_GT) ||
-                             (c == 0 && opcode & MASK_EQ)))
+                       if (!((opcode & MASK_LT && c < 0) ||
+                             (opcode & MASK_GT && c > 0) ||
+                             (opcode & MASK_EQ && c == 0)))
                                continue;
                        if (BUNlast(r1) == BATcapacity(r1)) {
                                newcap = BATgrows(r1);
@@ -953,3 +953,163 @@ BATsubthetajoin(BAT **r1p, BAT **r2p, BA
        *r2p = r2;
        return thetajoin(r1, r2, l, r, sl, sr, op);
 }
+
+gdk_return
+BATsubjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, BUN 
estimate)
+{
+       BAT *r1, *r2;
+       BUN lcount, rcount;
+       int swap;
+
+       *r1p = NULL;
+       *r2p = NULL;
+       if (joinparamcheck(l, r, sl, sr, "BATsubleftjoin") == GDK_FAIL)
+               return GDK_FAIL;
+       lcount = BATcount(l);
+       if (sl)
+               lcount = MIN(lcount, BATcount(sl));
+       rcount = BATcount(r);
+       if (sr)
+               rcount = MIN(rcount, BATcount(sr));
+       if (lcount == 0 || rcount == 0) {
+               r1 = BATnew(TYPE_void, TYPE_void, 0);
+               BATseqbase(r1, 0);
+               BATseqbase(BATmirror(r1), 0);
+               r2 = BATnew(TYPE_void, TYPE_void, 0);
+               BATseqbase(r2, 0);
+               BATseqbase(BATmirror(r2), 0);
+               *r1p = r1;
+               *r2p = r2;
+               return GDK_SUCCEED;
+       }
+       if (joininitresults(&r1, &r2, estimate != BUN_NONE ? estimate : sl ? 
BATcount(sl) : BATcount(l), "BATsubleftjoin") == GDK_FAIL)
+               return GDK_FAIL;
+       *r1p = r1;
+       *r2p = r2;
+       swap = 0;
+       if ((l->tsorted || l->trevsorted) && (r->tsorted || r->trevsorted)) {
+               /* both sorted, don't swap */
+               return mergejoin(r1, r2, l, r, sl, sr, 0, 0, 0);
+       } else if (l->T->hash && r->T->hash) {
+               /* both have hash, smallest on right */
+               if (lcount < rcount)
+                       swap = 1;
+       } else if (l->T->hash) {
+               /* only left has hash, swap */
+               swap = 1;
+       } else if (r->T->hash) {
+               /* only right has hash, don't swap */
+               swap = 0;
+       } else if (l->tsorted || l->trevsorted) {
+               /* left is sorted, swap */
+               return mergejoin(r2, r1, r, l, sr, sl, 0, 0, 0);
+       } else if (r->tsorted || r->trevsorted) {
+               /* right is sorted, don't swap */
+               return mergejoin(r1, r2, l, r, sl, sr, 0, 0, 0);
+       } else if (BATcount(r1) < BATcount(r2)) {
+               /* no hashes, not sorted, create hash on smallest BAT */
+               swap = 1;
+       }
+       if (swap) {
+               return hashjoin(r2, r1, r, l, sr, sl, 0, 0, 0);
+       } else {
+               return hashjoin(r1, r2, l, r, sl, sr, 0, 0, 0);
+       }
+}
+
+BAT *
+BATproject(BAT *l, BAT *r)
+{
+       BAT *bn;
+       const oid *o;
+       const void *nil = ATOMnilptr(r->ttype);
+       const void *v, *prev;
+       BATiter ri;
+       oid lo, hi;
+       BUN n;
+       int (*cmp)(const void *, const void *) = BATatoms[r->ttype].atomCmp;
+       int c;
+
+       assert(BAThdense(l));
+       assert(BAThdense(r));
+       assert(l->ttype == TYPE_void || l->ttype == TYPE_oid);
+
+       if (BATtdense(l)) {
+               lo = l->tseqbase;
+               hi = l->tseqbase + BATcount(l);
+               if (lo < r->hseqbase || hi > r->hseqbase + BATcount(r)) {
+                       GDKerror("BATproject: does not match always\n");
+                       return NULL;
+               }
+               bn = BATslice(r, lo - r->hseqbase, hi - r->hseqbase);
+               if (bn == NULL)
+                       return NULL;
+               return BATseqbase(bn, l->hseqbase + (lo - l->tseqbase));
+       }
+       if (l->ttype == TYPE_void) {
+               assert(l->tseqbase == oid_nil);
+               bn = BATconstant(r->ttype, nil, BATcount(l));
+               if (bn != NULL)
+                       bn = BATseqbase(bn, l->hseqbase);
+               return bn;
+       }
+       assert(l->ttype == TYPE_oid);
+       bn = BATnew(TYPE_void, r->ttype, BATcount(l));
+       if (bn == NULL)
+               return NULL;
+       o = (const oid *) Tloc(l, BUNfirst(l));
+       n = BUNfirst(bn);
+       ri = bat_iterator(r);
+       /* be optimistic, we'll change this as needed */
+       bn->T->nonil = 1;
+       bn->T->nil = 0;
+       bn->tsorted = 1;
+       bn->trevsorted = 1;
+       bn->tkey = 1;
+       prev = NULL;
+       for (lo = l->hseqbase, hi = lo + BATcount(l); lo < hi; lo++, o++, n++) {
+               if (*o == oid_nil) {
+                       tfastins_nocheck(bn, n, nil, Tsize(bn));
+                       bn->T->nonil = 0;
+                       bn->T->nil = 1;
+                       bn->tsorted = 0;
+                       bn->trevsorted = 0;
+                       bn->tkey = 0;
+               } else if (*o < r->hseqbase ||
+                          *o >= r->hseqbase + BATcount(r)) {
+                       GDKerror("BATproject: does not match always\n");
+                       goto bunins_failed;
+               } else {
+                       v = BUNtail(ri, *o - r->hseqbase + BUNfirst(r));
+                       tfastins_nocheck(bn, n, v, Tsize(bn));
+                       if (bn->T->nonil && cmp(v, nil) == 0) {
+                               bn->T->nonil = 0;
+                               bn->T->nil = 1;
+                       }
+                       if (prev && (bn->trevsorted | bn->tsorted | bn->tkey)) {
+                               c = cmp(prev, v);
+                               if (c < 0) {
+                                       bn->trevsorted = 0;
+                                       if (!bn->tsorted)
+                                               bn->tkey = 0; /* can't be sure 
*/
+                               }
+                               if (c > 0) {
+                                       bn->tsorted = 0;
+                                       if (!bn->trevsorted)
+                                               bn->tkey = 0; /* can't be sure 
*/
+                               }
+                               if (c == 0)
+                                       bn->tkey = 0; /* definitely */
+                       }
+                       prev = v;
+               }
+       }
+       assert(n == BATcount(l));
+       BATsetcount(bn, n);
+       BATseqbase(bn, l->hseqbase);
+       return bn;
+
+  bunins_failed:
+       BBPreclaim(bn);
+       return NULL;
+}
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to