Changeset: 56e6d2d4b168 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/56e6d2d4b168
Modified Files:
        gdk/gdk.h
        gdk/gdk_utils.c
        monetdb5/modules/mal/tablet.c
Branch: default
Log Message:

Merge with Dec2025 branch.


diffs (232 lines):

diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -1101,10 +1101,14 @@ BATsettrivprop(BAT *b)
                                /* the only value is NIL */
                                b->tminpos = BUN_NONE;
                                b->tmaxpos = BUN_NONE;
+                               b->tnil = true;
+                               b->tnonil = false;
                        } else {
                                /* the only value is both min and max */
                                b->tminpos = 0;
                                b->tmaxpos = 0;
+                               b->tnonil = true;
+                               b->tnil = false;
                        }
                } else {
                        b->tsorted = false;
diff --git a/gdk/gdk_utils.c b/gdk/gdk_utils.c
--- a/gdk/gdk_utils.c
+++ b/gdk/gdk_utils.c
@@ -2182,6 +2182,24 @@ ma_reset(allocator *sa)
 void *
 ma_realloc(allocator *sa, void *p, size_t sz, size_t oldsz)
 {
+       size_t r_oldsz = round16(oldsz);
+       size_t r_sz = round16(sz);
+       if (r_oldsz <= sa->used &&
+           (char *) sa->blks[sa->nr - 1] + sa->used - r_oldsz == (char *) p) {
+               /* trying to realloc the last allocated buffer, we may
+                * be able to readjust it */
+               if (sz <= oldsz) {
+                       /* size reduction */
+                       sa->used = sa->used - r_oldsz + r_sz;
+                       return p;
+               }
+               if (sa->used - r_oldsz + r_sz <= MA_BLOCK_SIZE) {
+                       sa->used = sa->used - r_oldsz + r_sz;
+                       return p;
+               }
+       } else if (r_sz <= r_oldsz)
+               return p;
+
        void *r = ma_alloc(sa, sz);
 
        if (r)
diff --git a/monetdb5/modules/mal/tablet.c b/monetdb5/modules/mal/tablet.c
--- a/monetdb5/modules/mal/tablet.c
+++ b/monetdb5/modules/mal/tablet.c
@@ -854,7 +854,8 @@ SQLinsert_val(READERtask *task, int col,
        char *err = NULL;
        int ret = 0;
        allocator *ta = MT_thread_getallocator();
-       allocator_state ta_state = ma_open(ta);
+       bool opened = false;            /* whether ma_open was called */
+       allocator_state ta_state = {0};
        allocator *ma = task->cntxt->curprg->def->ma;
 
        /* include testing on the terminating null byte !! */
@@ -864,7 +865,14 @@ SQLinsert_val(READERtask *task, int col,
        } else {
                if (task->escape) {
                        size_t slen = strlen(s) + 1;
-                       char *data = slen <= sizeof(buf) ? buf : ma_alloc(ta, 
strlen(s) + 1);
+                       char *data;
+                       if (slen <= sizeof(buf)) {
+                               data = buf;
+                       } else {
+                               ta_state = ma_open(ta);
+                               opened = true;
+                               data = ma_alloc(ta, strlen(s) + 1);
+                       }
                        if (data == NULL
                                || GDKstrFromStr((unsigned char *) data, 
(unsigned char *) s,
                                                                 strlen(s), 
'\0') < 0)
@@ -882,6 +890,10 @@ SQLinsert_val(READERtask *task, int col,
                if (task->rowerror) {
                        err = SQLload_error(task, idx, task->as->nr_attrs);
                        if (s) {
+                               if (!opened) {
+                                       ta_state = ma_open(ta);
+                                       opened = true;
+                               }
                                size_t slen = mystrlen(s);
                                char *scpy = ma_alloc(ta, slen + 1);
                                if (scpy == NULL) {
@@ -898,7 +910,8 @@ SQLinsert_val(READERtask *task, int col,
                                         s ? " in '" : "", s ? s : "", s ? "'" 
: "");
                        tablet_error(task, idx, row, col, buf, err);
                        if (!task->besteffort) {
-                               ma_close(&ta_state);
+                               if (opened)
+                                       ma_close(&ta_state);
                                return -1;
                        }
                }
@@ -908,7 +921,8 @@ SQLinsert_val(READERtask *task, int col,
                fmt->c->tnonil = false;
        }
        if (bunfastapp(fmt->c, adt) == GDK_SUCCEED) {
-               ma_close(&ta_state);
+               if (opened)
+                       ma_close(&ta_state);
                return ret;
        }
 
@@ -920,7 +934,8 @@ SQLinsert_val(READERtask *task, int col,
                                         && *msg ? msg : "insert failed", err);
        }
        task->besteffort = false;       /* no longer best effort */
-       ma_close(&ta_state);
+       if (opened)
+               ma_close(&ta_state);
        return -1;
 }
 
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -2856,7 +2856,7 @@ rel2bin_hash_lookup(backend *be, sql_rel
                        return stmt_join(be, h, idx, 0, cmp_equal, 0, 
semantics, false);
                }
        } else {
-               return stmt_uselect(be, idx, h, cmp_equal, NULL, 0, semantics);
+               return stmt_uselect(be, idx, h, cmp_equal, left->cand, 0, 
semantics);
        }
 }
 
@@ -4939,6 +4939,10 @@ rel2bin_select(backend *be, sql_rel *rel
                        sql_idx *i = p->value.pval;
                        int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
 
+                       if (sel) {
+                               sub->cand = sel;
+                               sel = NULL;
+                       }
                        if (!(sel = rel2bin_hash_lookup(be, rel, sub, NULL, i, 
en))) {
                                /* hash lookup cannot be used, clean leftover 
mal statements */
                                clean_mal_statements(be, oldstop, oldvtop);
diff --git a/sql/test/BugTracker-2026/Tests/7783-deleted-row.test 
b/sql/test/BugTracker-2026/Tests/7783-deleted-row.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2026/Tests/7783-deleted-row.test
@@ -0,0 +1,82 @@
+statement ok
+create table test (a int not null, b int not null, primary key (a, b))
+
+statement ok
+insert into test values (1, 1)
+
+statement ok
+delete from test where a = 1;
+
+statement ok
+insert into test values (1, 1)
+
+-- BUG: returns 2 identical rows (1, 1), this violates the constraint
+query II
+select * from test where a = 1 and b = 1
+----
+1
+1
+
+-- OK: returns 1 row
+query II
+select * from test where a = 1
+----
+1
+1
+
+query II
+select * from test where b = 1
+----
+1
+1
+
+query II
+select * from test
+----
+1
+1
+
+statement ok
+drop table test
+
+-- also happens with a composite unique constraint:
+statement ok
+create table test (a int, b int, unique (a, b))
+
+statement ok
+insert into test values (1, 1)
+
+statement ok
+delete from test where a = 1;
+
+statement ok
+insert into test values (1, 1)
+
+-- BUG: returns 2 identical rows (1, 1), this violates the constraint
+query II
+select * from test where a = 1 and b = 1
+----
+1
+1
+
+-- OK: returns 1 row
+query II
+select * from test where a = 1
+----
+1
+1
+
+query II
+select * from test where b = 1
+----
+1
+1
+
+query II
+select * from test
+----
+1
+1
+
+statement ok
+drop table test
diff --git a/sql/test/BugTracker-2026/Tests/All 
b/sql/test/BugTracker-2026/Tests/All
--- a/sql/test/BugTracker-2026/Tests/All
+++ b/sql/test/BugTracker-2026/Tests/All
@@ -1,1 +1,2 @@
 7780-unnest-slow
+7783-deleted-row
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to