Changeset: 46523e5afa06 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/46523e5afa06
Modified Files:
        gdk/gdk_batop.c
        gdk/gdk_bbp.c
        gdk/gdk_join.c
        gdk/gdk_private.h
        gdk/gdk_string.c
        sql/test/BugTracker-2026/Tests/All
Branch: pp_hashjoin
Log Message:

merged with default


diffs (truncated from 1171 to 300 lines):

diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml 
b/.github/ISSUE_TEMPLATE/bug_report.yml
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -74,6 +74,12 @@ body:
       placeholder: e.g., FooBar Corp
     validations:
       required: true
+  - type: checkboxes
+    attributes:
+      label: Please indicate if any LLM tools were used in preparing this 
report.
+      options:
+        - label: Yes, fully LLM generated
+        - label: Yes, LLM assisted
   - type: markdown
     attributes:
       value: |
diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c
--- a/gdk/gdk_batop.c
+++ b/gdk/gdk_batop.c
@@ -160,12 +160,9 @@ insert_string_bat(BAT *b, BATiter *ni, s
                toff = 0;
                b->tvkey |= ni->vkey;
                MT_thread_setalgorithm("shared vheap", __func__);
-       } else if (ni->vhfree <= GDK_STRHASHSIZE &&
-                  (!GDK_ELIMDOUBLES(b->tvheap) ||
-                   strLocate(b->tvheap, str_nil) == 0)) {
+       } else if (ni->vhfree <= GDK_STRHASHSIZE) {
                /* the incoming bat's vheap is empty, meaning the bat
-                * contains only nil values, if the destination bat's
-                * nil is also at offset 0, we can just copy zeros */
+                * contains only nil values: we can just copy zeros */
                toff = 0;
                MT_thread_setalgorithm("empty source vheap (just nils)",
                                       __func__);
@@ -173,13 +170,10 @@ insert_string_bat(BAT *b, BATiter *ni, s
                MT_thread_setalgorithm("individual inserts into ustr", 
__func__);
        } else if (mayshare && b->batRole == TRANSIENT &&
                   ni->vh->storage != STORE_NOWN &&
-                  (oldcnt == 0 || (b->tvheap->free <= GDK_STRHASHSIZE &&
-                                   (!GDK_ELIMDOUBLES(ni->vh) ||
-                                    strLocate(ni->vh, str_nil) == 0)))) {
+                  (oldcnt == 0 || b->tvheap->free <= GDK_STRHASHSIZE)) {
                /* we can share the vheaps, so we then only need to
                 * append the offsets; the condition is: b is empty, or
-                * its vheap is empty (i.e. there are only nils) and the
-                * incoming heap also stores them with offset 0 */
+                * its vheap is empty (i.e. there are only nils) */
                MT_lock_set(&b->theaplock);
                bat bid = b->tvheap->parentid;
                HEAPdecref(b->tvheap, bid == b->batCacheid);
@@ -3460,70 +3454,23 @@ BATcount_no_nil(BAT *b, BAT *s)
                        cnt += !is_inet6_nil(((const inet6 *) 
p)[canditer_next(&ci) - hseq]);
                break;
        case TYPE_str:
-               if (bi.vkey) {
-                       if (GDK_ELIMDOUBLES(bi.vh)) {
-                               off = strLocate(bi.vh, str_nil);
-                               if (off == (var_t) -2) {
-                                       cnt = ci.ncand;
-                                       break;
-                               }
-                       } else {
-                               off = 0;
-                       }
-                       switch (bi.width) {
-                       case 1:
-                               if (off != 0)
-                                       off -= GDK_VAROFFSET;
-                               CAND_LOOP(&ci)
-                                       cnt += (var_t) ((const uint8_t *) 
p)[canditer_next(&ci) - hseq] != off;
-                               break;
-                       case 2:
-                               if (off != 0)
-                                       off -= GDK_VAROFFSET;
-                               CAND_LOOP(&ci)
-                                       cnt += (var_t) ((const uint16_t *) 
p)[canditer_next(&ci) - hseq] != off;
-                               break;
-                       case 4:
-                               CAND_LOOP(&ci)
-                                       cnt += (var_t) ((const uint32_t *) 
p)[canditer_next(&ci) - hseq] != off;
-                               break;
-#if SIZEOF_VAR_T == 8
-                       case 8:
-                               CAND_LOOP(&ci)
-                                       cnt += (var_t) ((const uint64_t *) 
p)[canditer_next(&ci) - hseq] != off;
-                               break;
-#endif
-                       default:
-                               MT_UNREACHABLE();
-                       }
-                       break;
-               }
-               base = bi.vh->base;
                switch (bi.width) {
                case 1:
-                       CAND_LOOP(&ci) {
-                               off = (var_t) ((const uint8_t *) 
p)[canditer_next(&ci) - hseq];
-                               cnt += off != 0 && base[off + GDK_VAROFFSET] != 
'\200';
-                       }
+                       CAND_LOOP(&ci)
+                               cnt += (var_t) ((const uint8_t *) 
p)[canditer_next(&ci) - hseq] != 0;
                        break;
                case 2:
-                       CAND_LOOP(&ci) {
-                               off = (var_t) ((const uint16_t *) 
p)[canditer_next(&ci) - hseq];
-                               cnt += off != 0 && base[off + GDK_VAROFFSET] != 
'\200';
-                       }
+                       CAND_LOOP(&ci)
+                               cnt += (var_t) ((const uint16_t *) 
p)[canditer_next(&ci) - hseq] != 0;
                        break;
                case 4:
-                       CAND_LOOP(&ci) {
-                               off = (var_t) ((const uint32_t *) 
p)[canditer_next(&ci) - hseq];
-                               cnt += off != 0 && base[off] != '\200';
-                       }
+                       CAND_LOOP(&ci)
+                               cnt += (var_t) ((const uint32_t *) 
p)[canditer_next(&ci) - hseq] != 0;
                        break;
 #if SIZEOF_VAR_T == 8
                case 8:
-                       CAND_LOOP(&ci) {
-                               off = (var_t) ((const uint64_t *) 
p)[canditer_next(&ci) - hseq];
-                               cnt += off != 0 && base[off] != '\200';
-                       }
+                       CAND_LOOP(&ci)
+                               cnt += (var_t) ((const uint64_t *) 
p)[canditer_next(&ci) - hseq] != 0;
                        break;
 #endif
                default:
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -1650,6 +1650,305 @@ BBPjson_upgrade(json_storage_conversion 
 }
 #endif
 
+#ifdef GDKLIBRARY_USTR
+static bool file_exists(int farmid, const char *dir, const char *name, const 
char *ext);
+
+static gdk_return
+fixstrnilbat(BAT *b)
+{
+       lng t0 = GDKusec();
+       const char *nme = BBP_physical(b->batCacheid);
+       char srcdir[MAXPATH];
+       var_t niloff = 0;
+
+       if (GDKfilepath(srcdir, sizeof(srcdir), NOFARM, BATDIR, nme, NULL) != 
GDK_SUCCEED) {
+               return GDK_FAIL;
+       }
+       char *s;
+       if ((s = strrchr(srcdir, DIR_SEP)) != NULL)
+               *s = 0;
+       const char *bnme;
+       if ((bnme = strrchr(nme, DIR_SEP)) != NULL)
+               bnme++;
+       else
+               bnme = nme;
+       long_str filename;
+       strtconcat(filename, sizeof(filename), "BACKUP", DIR_SEP_STR, bnme, 
NULL);
+       const char *t = BATtailname(b);
+
+       if (file_exists(0, BAKDIR, bnme, t)) {
+               /* already done by another upgrade */
+               TRC_DEBUG(ALGO, ALGOBATFMT " already done\n", ALGOBATPAR(b));
+               return GDK_SUCCEED;
+       }
+
+       if (HEAPload(b->tvheap, nme, "theap", false) != GDK_SUCCEED) {
+               TRC_CRITICAL(GDK, "loading string heap "
+                            "for BAT %d failed\n", b->batCacheid);
+               return GDK_FAIL;
+       }
+       strCleanHash(b->tvheap, false);
+       b->tvheap->cleanhash = true;
+       b->tvheap->dirty = false;
+       if (GDK_ELIMDOUBLES(b->tvheap)) {
+               niloff = oldstrnilLocate(b->tvheap);
+               if (niloff == (var_t) -2) {
+                       /* fully double eliminated, and str_nil does not
+                        * occur: nothing to do */
+                       HEAPfree(b->tvheap, false);
+                       TRC_DEBUG(ALGO, ALGOBATFMT " elimdoubles, no nils\n",
+                                 ALGOBATPAR(b));
+                       return GDK_SUCCEED;
+               }
+       }
+
+       if (GDKmove(b->theap->farmid, srcdir, bnme, t,
+                   BAKDIR, bnme, t, false) != GDK_SUCCEED) {
+               HEAPfree(b->tvheap, false);
+               TRC_CRITICAL(GDK, "cannot make backup of %s.%s\n", nme, t);
+               return GDK_FAIL;
+       }
+
+       Heap h1 = *b->theap;    /* old heap */
+       h1.base = NULL;
+       h1.dirty = false;
+       strtconcat(h1.filename, sizeof(h1.filename), filename, ".", t, NULL);
+       if (HEAPload(&h1, filename, t, false) != GDK_SUCCEED) {
+               HEAPfree(b->tvheap, false);
+               TRC_CRITICAL(GDK, "loading old tail heap "
+                            "for BAT %d failed\n", b->batCacheid);
+               return GDK_FAIL;
+       }
+
+       /* create new heap */
+       Heap *h2 = GDKmalloc(sizeof(Heap));
+       if (h2 == NULL) {
+               HEAPfree(&h1, false);
+               HEAPfree(b->tvheap, false);
+               TRC_CRITICAL(GDK, "allocating new heaps "
+                            "for BAT %d failed\n", b->batCacheid);
+               return GDK_FAIL;
+       }
+       *h2 = *b->theap;
+       h2->base = NULL;
+       if (HEAPalloc(h2, b->batCapacity, b->twidth) != GDK_SUCCEED) {
+               GDKfree(h2);
+               HEAPfree(&h1, false);
+               HEAPfree(b->tvheap, false);
+               TRC_CRITICAL(GDK, "allocating new tail heap "
+                            "for BAT %d failed\n", b->batCacheid);
+               return GDK_FAIL;
+       }
+       h2->dirty = true;
+       h2->free = h1.free;
+       ATOMIC_INIT(&h2->refs, 1);
+
+       const char *vbase = b->tvheap->base;
+       size_t vfree = b->tvheap->free;
+       switch (b->twidth) {
+       case 1: {
+               const uint8_t *p1 = (const uint8_t *) h1.base;
+               uint8_t *p2 = (uint8_t *) h2->base;
+               vfree -= 8192;
+               niloff -= 8192;
+               for (BUN i = 0; i < b->batCount; i++) {
+                       uint8_t v = p1[i];
+                       if (v == niloff)
+                               p2[i] = 0;
+                       else if (v >= vfree || vbase[v + 8192] == '\200')
+                               p2[i] = 0;
+                       else
+                               p2[i] = v;
+               }
+               break;
+       }
+       case 2: {
+               const uint16_t *p1 = (const uint16_t *) h1.base;
+               uint16_t *p2 = (uint16_t *) h2->base;
+               vfree -= 8192;
+               niloff -= 8192;
+               for (BUN i = 0; i < b->batCount; i++) {
+                       uint16_t v = p1[i];
+                       if (v == niloff)
+                               p2[i] = 0;
+                       else if (v >= vfree || vbase[v + 8192] == '\200')
+                               p2[i] = 0;
+                       else
+                               p2[i] = v;
+               }
+               break;
+       }
+       case 4: {
+               const uint32_t *p1 = (const uint32_t *) h1.base;
+               uint32_t *p2 = (uint32_t *) h2->base;
+               for (BUN i = 0; i < b->batCount; i++) {
+                       uint32_t v = p1[i];
+                       if (v >= vfree || vbase[v] == '\200')
+                               p2[i] = 0;
+                       else
+                               p2[i] = v;
+               }
+               break;
+       }
+#if SIZEOF_VAR_T == 8
+       case 8: {
+               const uint64_t *p1 = (const uint64_t *) h1.base;
+               uint64_t *p2 = (uint64_t *) h2->base;
+               for (BUN i = 0; i < b->batCount; i++) {
+                       uint64_t v = p1[i];
+                       if (v >= vfree || vbase[v] == '\200')
+                               p2[i] = 0;
+                       else
+                               p2[i] = v;
+               }
+               break;
+       }
+#endif
+       default:
+               MT_UNREACHABLE();
+       }
+       HEAPfree(&h1, false);
+       HEAPfree(b->tvheap, false);
+       if (HEAPsave(h2, nme, t, true, h2->free, NULL) != GDK_SUCCEED) {
+               HEAPdecref(h2, true);
+               TRC_CRITICAL(GDK, "saving heap failed\n");
+               return GDK_FAIL;
+       }
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to