Changeset: 23a37f635d2b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=23a37f635d2b
Modified Files:
        gdk/gdk_hash.c
        gdk/gdk_storage.c
        geom/lib/libgeom.h
        geom/monetdb5/geom.c
        monetdb5/extras/rapi/rapi.c
        monetdb5/optimizer/opt_mergetable.c
        sql/backends/monet5/sql_statement.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_unnest.c
        sql/server/sql_query.c
        
sql/test/BugTracker-2008/Tests/select_not_wrong_result.SF-2080151.stable.out
        sql/test/subquery/Tests/subquery6.sql
        sql/test/subquery/Tests/subquery6.stable.out
        testing/Mtest.py.in
        tools/merovingian/daemon/handlers.c
Branch: default
Log Message:

Merged with Jun2020


diffs (truncated from 575 to 300 lines):

diff --git a/gdk/gdk_hash.c b/gdk/gdk_hash.c
--- a/gdk/gdk_hash.c
+++ b/gdk/gdk_hash.c
@@ -107,7 +107,11 @@ doHASHdestroy(BAT *b, Hash *hs)
                GDKunlink(BBPselectfarm(b->batRole, b->ttype, hashheap),
                          BATDIR,
                          BBP_physical(b->batCacheid),
-                         "thash");
+                         "thashl");
+               GDKunlink(BBPselectfarm(b->batRole, b->ttype, hashheap),
+                         BATDIR,
+                         BBP_physical(b->batCacheid),
+                         "thashb");
        } else if (hs) {
                bat p = VIEWtparent(b);
                BAT *hp = NULL;
diff --git a/gdk/gdk_storage.c b/gdk/gdk_storage.c
--- a/gdk/gdk_storage.c
+++ b/gdk/gdk_storage.c
@@ -887,10 +887,10 @@ BATdelete(BAT *b)
        assert(bid > 0);
        if (loaded) {
                b = loaded;
-               HASHdestroy(b);
-               IMPSdestroy(b);
-               OIDXdestroy(b);
        }
+       HASHdestroy(b);
+       IMPSdestroy(b);
+       OIDXdestroy(b);
        if (b->batCopiedtodisk || (b->theap.storage != STORE_MEM)) {
                if (b->ttype != TYPE_void &&
                    HEAPdelete(&b->theap, o, "tail") != GDK_SUCCEED &&
diff --git a/monetdb5/optimizer/opt_mergetable.c 
b/monetdb5/optimizer/opt_mergetable.c
--- a/monetdb5/optimizer/opt_mergetable.c
+++ b/monetdb5/optimizer/opt_mergetable.c
@@ -1959,9 +1959,12 @@ OPTmergetableImplementation(Client cntxt
                        bailout = 1;
                }
                if (getModuleId(p) == algebraRef &&
-                   getFunctionId(p) == thetajoinRef ) {
+                   getFunctionId(p) == thetajoinRef) {
+                     assert(p->argc == 9);
+                     if (p->argc == 9 && 
getVarConstant(mb,getArg(p,6)).val.ival == 6 /* op == '<>' */) {
                        TRC_INFO(MAL_OPTIMIZER, "Mergetable bailout thetajoin 
ref\n");
                        bailout = 1;
+                     }
                }
                if (isSample(p)) {
                        bailout = 1;
diff --git a/sql/backends/monet5/sql_statement.c 
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -2036,8 +2036,11 @@ stmt_semijoin(backend *be, stmt *op1, st
        if (op1->nr < 0 || op2->nr < 0)
                return NULL;
 
-       q = newStmt(mb, algebraRef, semijoinRef);
-       q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
+       if (single) {
+               q = newStmt(mb, algebraRef, semijoinRef);
+               q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
+       } else
+               q = newStmt(mb, algebraRef, intersectRef);
        q = pushArgument(mb, q, op1->nr);
        q = pushArgument(mb, q, op2->nr);
        if (lcand)
@@ -2060,7 +2063,9 @@ stmt_semijoin(backend *be, stmt *op1, st
                s->op2 = op2;
                s->flag = cmp_equal;
                s->key = 0;
-               s->nrcols = 2;
+               s->nrcols = 1;
+               if (single)
+                       s->nrcols = 2;
                s->nr = getDestVar(q);
                s->q = q;
                return s;
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -4101,7 +4101,7 @@ rel_merge_rse(mvc *sql, sql_rel *rel, in
 
 /* find in the list of expression an expression which uses e */ 
 static sql_exp *
-exp_uses_exp( list *exps, sql_exp *e)
+exps_uses_exp( list *exps, sql_exp *e)
 {
        node *n;
        const char *rname = exp_relname(e);
@@ -4246,7 +4246,7 @@ rel_push_aggr_down(mvc *sql, sql_rel *re
                        for (n = ogbe->h; n; n = n->next) { 
                                sql_exp *e = n->data, *ne;
 
-                               ne = exp_uses_exp( rel->exps, e);
+                               ne = exps_uses_exp( rel->exps, e);
                                if (!ne)
                                        continue;
                                ne = list_find_exp( u->exps, ne);
@@ -4780,11 +4780,11 @@ rel_push_join_down(mvc *sql, sql_rel *re
 
                                /* project in between, ie find alias */
                                /* first find expression in expression list */
-                               gbe = exp_uses_exp( gb->exps, gbe);
+                               gbe = exps_uses_exp( gb->exps, gbe);
                                if (!gbe)
                                        continue;
                                if (ogb != gb) 
-                                       gbe = exp_uses_exp( ogb->exps, gbe);
+                                       gbe = exps_uses_exp( ogb->exps, gbe);
                                if (gbe) {
                                        rname = exp_find_rel_name(gbe);
                                        name = exp_name(gbe);
@@ -5340,6 +5340,96 @@ rel_remove_empty_join(mvc *sql, sql_rel 
        return rel;
 }
 
+/* const or groupby without group by exps */
+#define SIMPLE_PROJECTION_FOR_JOIN2SEMI(X) \
+       ((X)->card < CARD_AGGR && is_project((X)->op) && list_length((X)->exps) 
== 1)
+
+static sql_rel * 
+find_candidate_join2semi(sql_rel *rel, bool *swap) 
+{
+       /* generalize possibility : we need the visitor 'step' here */
+       if (rel->op == op_join && rel->exps) {
+               sql_rel *l = rel->l, *r = rel->r;
+
+               if (SIMPLE_PROJECTION_FOR_JOIN2SEMI(r)) {
+                       *swap = false;
+                       return rel;
+               }
+               if (SIMPLE_PROJECTION_FOR_JOIN2SEMI(l)) {
+                       *swap = true;
+                       return rel;
+               }
+       }
+       if (is_join(rel->op) || is_semi(rel->op)) {
+               sql_rel *c;
+
+               if ((c=find_candidate_join2semi(rel->l, swap)) != NULL ||
+                   (c=find_candidate_join2semi(rel->r, swap)) != NULL) 
+                       return c;
+       }
+       return NULL;
+}
+
+static int
+subrel_uses_exp_outside_subrel(sql_rel *rel, sql_exp *e, sql_rel *c)
+{
+       if (rel == c)
+               return 0;
+       /* for subrel only expect joins (later possibly selects) */ 
+       if (is_join(rel->op) || is_semi(rel->op)) {
+               if (exps_uses_exp(rel->exps, e))
+                       return 1;
+               if (subrel_uses_exp_outside_subrel(rel->l, e, c) ||
+                   subrel_uses_exp_outside_subrel(rel->r, e, c))
+                       return 1;
+       }
+       return 0;
+}
+
+static int
+rel_uses_exp_outside_subrel(sql_rel *rel, sql_exp *e, sql_rel *c)
+{
+       /* for now we only expect sub relations of type project, selects (rel) 
or join/semi */ 
+       if (is_simple_project(rel->op) || is_groupby(rel->op) || 
is_select(rel->op)) {
+               if (!list_empty(rel->exps) && exps_uses_exp(rel->exps, e))
+                       return 1;
+               if ((is_simple_project(rel->op) || is_groupby(rel->op)) && 
!list_empty(rel->r) && exps_uses_exp(rel->r, e))
+                       return 1;
+               if (rel->l)
+                       return subrel_uses_exp_outside_subrel(rel->l, e, c);
+       }
+       return 1;
+}
+
+static sql_rel *
+rel_join2semijoin(mvc *sql, sql_rel *rel, int *changes)
+{
+       (void)sql;
+       if ((is_simple_project(rel->op) || is_groupby(rel->op) || 
is_select(rel->op)) && rel->l) {
+               bool swap = false;
+               sql_rel *l = rel->l;
+               sql_rel *c = find_candidate_join2semi(l, &swap);
+
+               if (c) {
+                       /* 'p' is a project and only has one result */
+                       sql_rel *p = swap ? c->l : c->r;
+                       sql_exp *re = p->exps->h->data;
+
+                       /* now we need to check if ce is only used at the level 
of c */
+                       if (!rel_uses_exp_outside_subrel(rel, re, c)) {
+                               c->op = op_semi;
+                               if (swap) {
+                                       sql_rel *tmp = c->r;
+                                       c->r = c->l;
+                                       c->l = tmp;
+                               }
+                               (*changes)++;
+                       }
+               }
+       }
+       return rel;
+}
+
 typedef struct {
        sql_rel *p; /* the found join's parent */
        sql_rel *j; /* the found join relation itself */
@@ -9076,6 +9166,8 @@ optimize_rel(mvc *sql, sql_rel *rel, int
 
        if (gp.cnt[op_join] || gp.cnt[op_left] || gp.cnt[op_right] || 
gp.cnt[op_full] || gp.cnt[op_semi] || gp.cnt[op_anti]) {
                rel = rel_remove_empty_join(sql, rel, &changes);
+
+               rel = rel_visitor_bottomup(sql, rel, &rel_join2semijoin, 
&changes); 
                if (!gp.cnt[op_update])
                        rel = rel_join_order(sql, rel);
                rel = rel_visitor_bottomup(sql, rel, &rel_push_join_down_union, 
&changes); 
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -432,6 +432,7 @@ rel_inplace_project(sql_allocator *sa, s
                        return NULL;
 
                *l = *rel;
+               l->ref.refcnt = 1;
        } else {
                rel_destroy_(rel);
        }
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -732,6 +732,14 @@ rel_general_unnest(mvc *sql, sql_rel *re
                int nr;
 
                sql_rel *l = rel->l, *r = rel->r, *inner_r;
+
+               /* cleanup empty selects (should be done before any rel_dup(l) 
*/
+               if (l && is_select(l->op) && list_empty(l->exps) && 
!rel_is_ref(l)) {
+                       rel->l = l->l;
+                       l->l = NULL;
+                       rel_destroy(l);
+                       l = rel->l;
+               }
                /* rewrite T1 dependent join T2 -> T1 join D dependent join T2, 
where the T1/D join adds (equality) predicates (for the Domain (ad)) and D is 
are the distinct(projected(ad) from T1)  */
                sql_rel *D = rel_project(sql->sa, rel_dup(l), exps_copy(sql, 
ad));
                set_distinct(D);
@@ -1480,7 +1488,7 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && is_groupby(r->op) && need_distinct(l) /*&& 
is_distinct_set(sql, l, ad)*/) { 
+                       if (r && is_groupby(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad)) {
                                rel = push_up_groupby(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
@@ -1490,7 +1498,7 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && is_set(r->op) && (!is_left(rel->op) && 
is_distinct_set(sql, l, ad))) {
+                       if (r && is_set(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad)) {
                                rel = push_up_set(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
@@ -2333,7 +2341,7 @@ rewrite_compare(mvc *sql, sql_rel *rel, 
                        } else {
                                if (lsq) 
                                        (void)rewrite_inner(sql, rel, lsq, 
op_join);
-                               if (rsq) 
+                               if (rsq)
                                        (void)rewrite_inner(sql, rel, rsq, 
!is_tuple?op_join:is_anyequal(sf)?op_semi:op_anti);
                                if (is_tuple) {
                                        list *t = le->f;
@@ -3034,6 +3042,8 @@ rel_unnest(mvc *sql, sql_rel *rel)
        rel = rel_visitor_bottomup(sql, rel, &rewrite_values, &changes);
        rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_exp_rel, &changes);
        rel = rel_visitor_bottomup(sql, rel, &rewrite_join2semi, &changes);     
/* where possible convert anyequal functions into marks */
+       if (changes > 0)
+               rel = rel_visitor_bottomup(sql, rel, &rel_remove_empty_select, 
&changes);
        rel = rel_visitor_bottomup(sql, rel, &rewrite_compare_exp, &changes);   
/* only allow for e_cmp in selects and  handling */
        rel = rel_visitor_bottomup(sql, rel, &rewrite_remove_xp_project, 
&changes);     /* remove crossproducts with project ( project [ atom ] ) [ etc 
] */
        changes = 0;
diff --git a/sql/server/sql_query.c b/sql/server/sql_query.c
--- a/sql/server/sql_query.c
+++ b/sql/server/sql_query.c
@@ -102,10 +102,10 @@ query_outer_used_exp(sql_query *q, int i
 
        sq->last_used = e;
        sq->used_card = sq->rel->card;
-       assert( (!is_sql_aggr(f) && sq->grouped == 0 && e->card > CARD_AGGR) || 
/* outer is a none grouped relation */
+       assert( (!is_sql_aggr(f) && sq->grouped == 0 && e->card != CARD_AGGR) 
|| /* outer is a none grouped relation */
                (!is_sql_aggr(f) && sq->grouped == 1 && e->card <= CARD_AGGR) 
|| /* outer is groupbed, ie only return aggregations or groupby cols */
-               (is_sql_aggr(f) && !is_sql_farg(f) && !sq->grouped && e->card > 
CARD_AGGR) || /* a column to be aggregated */
-               (is_sql_aggr(f) && !is_sql_farg(f) && sq->grouped && e->card > 
CARD_AGGR) || /* a column to be aggregated */
+               (is_sql_aggr(f) && !is_sql_farg(f) && !sq->grouped && e->card 
!= CARD_AGGR) || /* a column/constant to be aggregated */
+               (is_sql_aggr(f) && !is_sql_farg(f) && sq->grouped && e->card != 
CARD_AGGR) || /* a column/constant to be aggregated */
                (is_sql_aggr(f) && is_sql_farg(f) && sq->grouped && e->card <= 
CARD_AGGR) ||  /* groupby ( function (group by col)) */
                (is_sql_aggr(f) && sq->grouped && e->card <= CARD_AGGR) ); /* 
nested aggregations is handled later */
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to