Changeset: 037f5688e752 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/037f5688e752
Added Files:
        
sql/test/BugTracker-2026/Tests/7974-multi-column-not-in-subquery-bug.test
Removed Files:
        sql/test/BugTracker-2026/Tests/7974-muli-column-not-in-subquery-bug.test
Modified Files:
        monetdb5/modules/mal/pp_hash.c
        sql/backends/monet5/rel_pphash.c
        sql/server/rel_optimize_sel.c
        sql/test/BugTracker-2026/Tests/All
Branch: manti
Log Message:

some fixes in manti impl. for some boundary cases.

* rel_optimize_sel.c: don't attempt to optimize a (marked) group join (i.e.
op_join && rel->attr).  This avoids rewriting some left-outer-joins into a cross
product

* pp_hash.c:
  * OAHASHbuild(): guarde h->empty with a lock
  * OAHASHexpand3: handle the case of ht->empty

* rel_pphash.c: don't filter out the FALSE rows after mprobe, we need their OIDs
in prb_oid for the final results.

* BugTracker-2026:
  * enabled the test 7974
  * corrected a typo in the name of the test


diffs (158 lines):

diff --git a/monetdb5/modules/mal/pp_hash.c b/monetdb5/modules/mal/pp_hash.c
--- a/monetdb5/modules/mal/pp_hash.c
+++ b/monetdb5/modules/mal/pp_hash.c
@@ -1601,13 +1601,13 @@ OAHASHbuild(Client ctx, MalBlkPtr m, Mal
                int tt = b->ttype;
                gid *gp = Tloc(g, 0);
 
-               h->empty = false;
                int slots = 0;
                gid slot = 0;
                QryCtx *qry_ctx = MT_thread_get_qry_ctx();
                qry_ctx = qry_ctx ? qry_ctx : &(QryCtx) {.endtime = 0};
 
                ht_activate(h);
+               h->empty = false;
                if (!parents) {
                        switch(tt) {
                                case TYPE_void:
@@ -3645,7 +3645,7 @@ OAHASHexpand3(Client ctx, MalBlkPtr mbp,
        QryCtx *qry_ctx = MT_thread_get_qry_ctx();
        qry_ctx = qry_ctx ? qry_ctx : &(QryCtx) {.endtime = 0};
        gid *allgids = NULL;
-       if (selcnt) {
+       if (selcnt && !ht->empty) {
                /* ht->last marks the maximal possible value in ht->gids, but 
we need
                 * to go over all of ht->size to find the gids. */
                allgids = GDKzalloc(ht->last * sizeof(gid));
@@ -3667,6 +3667,8 @@ OAHASHexpand3(Client ctx, MalBlkPtr mbp,
                TIMEOUT_CHECK(qry_ctx, err = createException(SQL, 
"oahash.expand", RUNTIME_QRY_TIMEOUT));
                if (err)
                        goto error;
+       } else {
+               xpdcnt = selcnt;
        }
 
        ep = COLnew(0, TYPE_oid, xpdcnt, TRANSIENT);
@@ -3681,39 +3683,48 @@ OAHASHexpand3(Client ctx, MalBlkPtr mbp,
        bit *resm = Tloc(em, 0);
 
        BUN idx = 0;
-       TIMEOUT_LOOP_IDX_DECL(i, selcnt, qry_ctx) {
-               if (is_oid_nil(gids[i])) {
-                       /* expand a NULL to all of ht->gids */
-                       TIMEOUT_LOOP_IDX_DECL(j, hpcnt, qry_ctx) {
+       if (ht->empty) {
+               TIMEOUT_LOOP_IDX_DECL(i, selcnt, qry_ctx) {
                                resp[idx] = oids[i];
-                               resh[idx] = allgids[j];
+                               resh[idx] = gids[i];
+                               resm[idx] = mrks[i];
+                               idx++;
+               }
+       } else {
+               TIMEOUT_LOOP_IDX_DECL(i, selcnt, qry_ctx) {
+                       if (is_oid_nil(gids[i])) {
+                               /* expand a NULL to all of ht->gids */
+                               TIMEOUT_LOOP_IDX_DECL(j, hpcnt, qry_ctx) {
+                                       resp[idx] = oids[i];
+                                       resh[idx] = allgids[j];
+                                       resm[idx] = mrks[i];
+                                       idx++;
+                               }
+                       } else if (freq) {
+                               gid frq = (gid)freq[gids[i]];
+                               assert(frq);
+                               int prime = hash_prime_nr[ht->bits-5];
+                               TIMEOUT_LOOP_IDX_DECL(j, frq, qry_ctx) {
+                                       oid k = (gid)combine(gids[i], 
oidHash(&j), prime) & ht->mask;
+                                       hash_key_t hk = ht->gids[k];
+                                       while (hk && (ht->pgids[hk] != gids[i] 
|| ((oid*)ht->vals)[hk] != j)) {
+                                               k++;
+                                               k &= ht->mask;
+                                               hk = ht->gids[k];
+                                       }
+                                       assert(hk > 0);
+
+                                       resp[idx] = oids[i];
+                                       resh[idx] = (oid)(hk-1);
+                                       resm[idx] = mrks[i];
+                                       idx++;
+                               }
+                       } else {
+                               resp[idx] = oids[i];
+                               resh[idx] = gids[i];
                                resm[idx] = mrks[i];
                                idx++;
                        }
-               } else if (freq) {
-                       gid frq = (gid)freq[gids[i]];
-                       assert(frq);
-                       int prime = hash_prime_nr[ht->bits-5];
-                       TIMEOUT_LOOP_IDX_DECL(j, frq, qry_ctx) {
-                               oid k = (gid)combine(gids[i], oidHash(&j), 
prime) & ht->mask;
-                               hash_key_t hk = ht->gids[k];
-                               while (hk && (ht->pgids[hk] != gids[i] || 
((oid*)ht->vals)[hk] != j)) {
-                                       k++;
-                                       k &= ht->mask;
-                                       hk = ht->gids[k];
-                               }
-                               assert(hk > 0);
-
-                               resp[idx] = oids[i];
-                               resh[idx] = (oid)(hk-1);
-                               resm[idx] = mrks[i];
-                               idx++;
-                       }
-               } else {
-                       resp[idx] = oids[i];
-                       resh[idx] = gids[i];
-                       resm[idx] = mrks[i];
-                       idx++;
                }
        }
        TIMEOUT_CHECK(qry_ctx, err = createException(SQL, "oahash.expand", 
RUNTIME_QRY_TIMEOUT));
diff --git a/sql/backends/monet5/rel_pphash.c b/sql/backends/monet5/rel_pphash.c
--- a/sql/backends/monet5/rel_pphash.c
+++ b/sql/backends/monet5/rel_pphash.c
@@ -552,13 +552,6 @@ rel2bin_oahash_equi_join(backend *be, sq
                prb_oid = stmt_blackbox_result(be, prb_res->q, 0, tpe_oid);
                hsh_gid = stmt_blackbox_result(be, prb_res->q, 1, tpe_oid);
                mrk     = stmt_blackbox_result(be, prb_res->q, 2, tpe_bit);
-               /* Get only the rows that are !FALSE */
-               /* TODO: optimisation: add an oahash.mnprobe() to return only 
the rows that are !FALSE! */
-               stmt *sel = stmt_thetaselect(be, mrk, NULL, stmt_bool(be, 0), 
"ne", tpe_oid);
-               prb_oid = stmt_project(be, sel, prb_oid);
-               hsh_gid = stmt_project(be, sel, hsh_gid);
-               mrk     = stmt_project(be, sel, mrk);
-
                /* compute the prb_oid and hsh_gid (from hp_pos) to process the 
"payload" columns */
                stmt *expd = stmt_oahash_expand3(be, prb_oid, hsh_gid, mrk, 
hp_pos, freq);
                prb_oid = stmt_blackbox_result(be, expd->q, 0, tpe_oid);
diff --git a/sql/server/rel_optimize_sel.c b/sql/server/rel_optimize_sel.c
--- a/sql/server/rel_optimize_sel.c
+++ b/sql/server/rel_optimize_sel.c
@@ -1609,7 +1609,7 @@ rel_outer2inner(visitor *v, list *exps, 
 {
        if (!rel || rel_is_ref(rel))
                return rel;
-       if (rel->op == op_join /*is_join(rel->op) later nested outers as well 
*/ || is_select(rel->op)) {
+       if ((rel->op == op_join && list_empty(rel->attr)) /*is_join(rel->op) 
later nested outers as well */ || is_select(rel->op)) {
                if (!list_empty(rel->exps)) {
                        list *nexps = list_dup(exps, NULL);
                        for (node *n = rel->exps->h; n; n = n->next) {
diff --git 
a/sql/test/BugTracker-2026/Tests/7974-muli-column-not-in-subquery-bug.test 
b/sql/test/BugTracker-2026/Tests/7974-multi-column-not-in-subquery-bug.test
rename from 
sql/test/BugTracker-2026/Tests/7974-muli-column-not-in-subquery-bug.test
rename to 
sql/test/BugTracker-2026/Tests/7974-multi-column-not-in-subquery-bug.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
@@ -159,7 +159,7 @@ PIPELINE?7966-optimize-select-distinct-f
 7971-prepare-decimal-parameter-crash
 7972-orderby-limit-subquery-bug
 7973-groupby-list-null-row-bug
-KNOWNFAIL?7974-muli-column-not-in-subquery-bug
+7974-multi-column-not-in-subquery-bug
 7975-cleanup-join-exps
 7976-dump_database-composite-key-order-bug
 7977-prepare-optimize
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to