Changeset: d3aa4c7ab5ea for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d3aa4c7ab5ea
Branch: default
Log Message:

Merge branch setjoins into default.


diffs (truncated from 715 to 300 lines):

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
@@ -2075,7 +2075,7 @@ OPTmergetableImplementation(Client cntxt
                 * 3 -> (l,r) range-joins (l,r1,r2)
                 * NxM -> (l,r) filter-joins (l1,..,ln,r1,..,rm)
                 */
-               if (match > 0 && isMatJoinOp(p) &&
+               if (match > 0 && isMatJoinOp(p) && !isMatLeftJoinOp(p) &&
                        p->argc >= 5 && p->retc == 2 && bats+nilbats >= 4) {
                        if (bats+nilbats == 4) {
                                m = is_a_mat(getArg(p,p->retc), &ml);
diff --git a/monetdb5/optimizer/opt_postfix.c b/monetdb5/optimizer/opt_postfix.c
--- a/monetdb5/optimizer/opt_postfix.c
+++ b/monetdb5/optimizer/opt_postfix.c
@@ -32,7 +32,7 @@ OPTpostfixImplementation(Client cntxt, M
 /* POSTFIX ACTION FOR THE JOIN CASE  */
                p= getInstrPtr(mb, i);
                if ( getModuleId(p) == algebraRef && p->retc == 2) {
-                       if ( getFunctionId(p) == leftjoinRef || 
getFunctionId(p) == outerjoinRef ||
+                       if ( getFunctionId(p) == leftjoinRef || 
/*getFunctionId(p) == outerjoinRef ||*/
                                 getFunctionId(p) == bandjoinRef || 
getFunctionId(p) == rangejoinRef ||
                                 getFunctionId(p) == likejoinRef) {
                                if ( getVarEolife(mb, getArg(p, p->retc -1)) == 
i) {
@@ -42,7 +42,7 @@ OPTpostfixImplementation(Client cntxt, M
                                        continue;
                                }
                        } else if ( getFunctionId(p) == semijoinRef || 
getFunctionId(p) == joinRef ||
-                                getFunctionId(p) == thetajoinRef || 
getFunctionId(p) == outerjoinRef || getFunctionId(p) == crossRef) {
+                                getFunctionId(p) == thetajoinRef || 
/*getFunctionId(p) == outerjoinRef ||*/ getFunctionId(p) == crossRef) {
                                int is_first_ret_not_used = getVarEolife(mb, 
getArg(p, p->retc -2)) == i;
                                int is_second_ret_not_used = getVarEolife(mb, 
getArg(p, p->retc -1)) == i;
 
diff --git a/monetdb5/optimizer/opt_support.c b/monetdb5/optimizer/opt_support.c
--- a/monetdb5/optimizer/opt_support.c
+++ b/monetdb5/optimizer/opt_support.c
@@ -611,7 +611,7 @@ inline int
 isMatLeftJoinOp(InstrPtr p)
 {
        return (getModuleId(p) == algebraRef &&
-               getFunctionId(p) == leftjoinRef);
+               (getFunctionId(p) == leftjoinRef || getFunctionId(p) == 
outerjoinRef));
 }
 
 inline int isDelta(InstrPtr p){
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
@@ -2701,6 +2701,25 @@ rel2bin_join(backend *be, sql_rel *rel, 
                s = stmt_alias(be, s, rnme, nme);
                list_append(l, s);
        }
+       if (rel->attr) {
+               sql_exp *e = rel->attr->h->data;
+               const char *rnme = exp_relname(e);
+               const char *nme = exp_name(e);
+               stmt *last = l->t->data;
+               sql_subtype *tp = tail_type(last);
+
+               sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", tp, 
NULL, F_FUNC);
+
+               stmt *s = stmt_unop(be, last, NULL, isnil);
+
+               sql_subtype *bt = sql_bind_localtype("bit");
+               sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, 
NULL, F_FUNC);
+
+               s = stmt_unop(be, s, NULL, not);
+               s = stmt_alias(be, s, rnme, nme);
+               list_append(l, s);
+       }
+
        res = stmt_list(be, l);
        res->extra = l2; /* used for merge statments, this will be cleaned out 
on the pushcands branch :) */
        return res;
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
@@ -1454,13 +1454,16 @@ stmt_uselect(backend *be, stmt *op1, stm
                const char *mod = calcRef;
                const char *op = "=";
                int k;
+               int notin = 0;
 
                switch (cmptype) {
                case mark_in:
-               case mark_notin:
                case cmp_equal:
                        op = "=";
                        break;
+               case mark_notin:
+                       notin = 1;
+                       /* fall through */
                case cmp_notequal:
                        op = "!=";
                        break;
@@ -1498,6 +1501,14 @@ stmt_uselect(backend *be, stmt *op1, stm
                        q = pushBit(mb, q, TRUE);
                k = getDestVar(q);
 
+               if (notin) {
+                       q = newStmt(mb, batcalcRef, "ifthenelse");
+                       q = pushArgument(mb, q, k);
+                       q = pushBit(mb, q, FALSE);
+                       q = pushBit(mb, q, TRUE);
+                       k = getDestVar(q);
+               }
+
                q = newStmtArgs(mb, algebraRef, selectRef, 9);
                q = pushArgument(mb, q, k);
                if (sub)
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -279,6 +279,13 @@ typedef struct relation {
        void *l;
        void *r;
        list *exps;
+       list *attr; /* attributes: mark-joins return extra attributes */
+                               /* later put all 'projection' attributes in 
here, ie for set ops, project/group/table/basetable by
+                                * select/ (semi/anti/left/outer/right)join 
will use exps for predicates
+                                * groupby will use exps for group by exps
+                                * project can use exps for the order by bits
+                                * topn/sample use exps for the input arguments 
of the limit/sample
+                                */
        int nrcols;     /* nr of cols */
        unsigned int
         flag:16,
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -550,6 +550,8 @@ rel_print_(mvc *sql, stream  *fout, sql_
                print_indent(sql, fout, depth, decorate);
                mnstr_printf(fout, ")");
                exps_print(sql, fout, rel->exps, depth, refs, 1, 0);
+               if (is_join(rel->op) && rel->attr) /* mark joins */
+                       exps_print(sql, fout, rel->attr, depth, refs, 1, 0);
                break;
        case op_project:
        case op_select:
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
@@ -4671,7 +4671,7 @@ rel_push_join_exps_down(visitor *v, sql_
                                rel_select_add_exp(v->sql->sa, rel->l, e);
                                list_remove_node(rel->exps, NULL, n);
                                v->changes++;
-                       } else if (right && (rel->op != op_anti || (e->flag != 
mark_notin && e->flag != mark_in)) &&
+                       } else if (right && ((rel->op != op_anti && rel->op != 
op_left) || (e->flag != mark_notin && e->flag != mark_in)) &&
                                           rel_rebind_exp(v->sql, rel->r, e)) { 
/* select expressions on right */
                                sql_rel *r = rel->r;
                                if (!is_select(r->op) || rel_is_ref(r)) {
@@ -6508,6 +6508,8 @@ rel_push_project_up(visitor *v, sql_rel 
                } else if (is_join(rel->op)) {
                        list *r_exps = rel_projections(v->sql, r, NULL, 1, 1);
                        list_merge(exps, r_exps, (fdup)NULL);
+                       if (rel->attr)
+                               append(exps, exp_ref(v->sql, 
rel->attr->h->data));
                }
                /* Here we should check for ambigious names ? */
                if (is_join(rel->op) && r) {
@@ -6515,6 +6517,8 @@ rel_push_project_up(visitor *v, sql_rel 
                        l_exps = rel_projections(v->sql, t, NULL, 1, 1);
                        /* conflict with old right expressions */
                        r_exps = rel_projections(v->sql, r, NULL, 1, 1);
+                       if (rel->attr)
+                               append(r_exps, exp_ref(v->sql, 
rel->attr->h->data));
                        for(n = l_exps->h; n; n = n->next) {
                                sql_exp *e = n->data;
                                const char *rname = exp_relname(e);
@@ -9876,6 +9880,103 @@ need_optimization(mvc *sql, sql_rel *rel
        return 2;
 }
 
+static sql_rel *
+rel_setjoins_2_joingroupby(visitor *v, sql_rel *rel)
+{
+       if (rel && is_join(rel->op) && (rel->exps || rel->attr)) {
+               sql_exp *me = NULL;
+               int needed = 0;
+               if (rel->exps) {
+                       for (node *n = rel->exps->h; n; n = n->next) {
+                               sql_exp *e = n->data;
+
+                               if (e->type == e_cmp && (e->flag == mark_in || 
e->flag == mark_notin)) {
+                                       me = e;
+                                       needed++;
+                               }
+                       }
+               }
+               if (needed && rel->op == op_join) {
+                       rel->op = (me->flag == mark_in)?op_semi:op_anti;
+                       return rel;
+               }
+               if (needed || rel->attr) {
+                       assert(needed || rel->attr);
+                       sql_exp *nequal = NULL;
+                       sql_exp *lid = NULL, *rid = NULL;
+                       sql_rel *l = rel->l, *p = rel;
+                       sql_rel *pp = NULL; /* maybe one project in between 
(TODO keep list) */
+
+                       if (me && rel->op == op_left) {
+                               /* find parent of join involving the right hand 
side of the mark expression */
+                               sql_rel *c = p->r;
+                               while (c) {
+                                       if (is_join(c->op) && 
rel_find_exp(c->r, me->r)) {
+                                               p = c;
+                                               c = p->r;
+                                       } if (!pp && is_project(c->op) && c->l 
&& rel_find_exp(c->l, me->r)) {
+                                               pp = c;
+                                               c = c->l;
+                                       } else {
+                                               c = NULL;
+                                       }
+                               }
+                       }
+                       if (p && p->r == pp)
+                               pp = NULL;
+
+                       rel->l = l = rel_add_identity(v->sql, l, &lid);
+                       lid = exp_ref(v->sql, lid);
+                       if (rel->op == op_left) {
+                               p->r = rel_add_identity(v->sql, p->r, &rid);
+                               rid = exp_ref(v->sql, rid);
+                               if (pp) {
+                                       append(pp->exps, rid);
+                                       rid = exp_ref(v->sql, rid);
+                               }
+                       }
+
+                       list *nexps = sa_list(v->sql->sa);
+                       list *aexps = sa_list(v->sql->sa);
+                       if (rel->exps) {
+                               for (node *n = rel->exps->h; n; n = n->next) {
+                                       sql_exp *e = n->data;
+
+                                       if (e->type == e_cmp && (e->flag == 
mark_in || e->flag == mark_notin)) {
+                                               sql_exp *le = e->l;
+                                               sql_exp *re = e->r;
+                                               sql_subfunc *ea = 
sql_bind_func(v->sql, "sys", e->flag==mark_in?"anyequal":"allnotequal", 
exp_subtype(re), NULL, F_AGGR);
+
+                                               sql_exp *ne = 
exp_aggr1(v->sql->sa, le, ea, 0, 0, CARD_AGGR, has_nil(le));
+                                               append(ne->l, re);
+                                               if (rid)
+                                                       append(ne->l, rid);
+
+                                               append(aexps, ne);
+                                               nequal = ne;
+                                       } else
+                                               append(nexps, e);
+                               }
+                       }
+                       rel->exps = nexps;
+
+                       if (rel->attr) {
+                               sql_exp *a = rel->attr->h->data;
+
+                               exp_setname(v->sql->sa, nequal, 
exp_find_rel_name(a), exp_name(a));
+                               rel->attr = NULL;
+                       } else {
+                               exp_label(v->sql->sa, nequal, ++v->sql->label);
+                       }
+                       list *lexps = rel_projections(v->sql, l, NULL, 1, 1);
+                       aexps = list_merge(aexps, lexps, (fdup)NULL);
+                       rel = rel_groupby(v->sql, rel, exp2list(v->sql->sa, 
lid));
+                       rel->exps = aexps;
+               }
+       }
+       return rel;
+}
+
 /* 'instantiate' means to rewrite logical tables: (merge, remote, replica 
tables) */
 sql_rel *
 rel_optimizer(mvc *sql, sql_rel *rel, int instantiate, int value_based_opt, 
int storage_based_opt)
@@ -9916,5 +10017,6 @@ rel_optimizer(mvc *sql, sql_rel *rel, in
                v.data = &level;
                rel = rel_visitor_bottomup(&v, rel, &rel_remote_func);
        }
+       rel = rel_visitor_bottomup(&v, rel, &rel_setjoins_2_joingroupby);
        return rel;
 }
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
@@ -948,7 +948,7 @@ exps_reset_props(list *exps, bool setnil
 list *
 _rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int 
intern, int basecol /* basecol only */ )
 {
-       list *lexps, *rexps, *exps;
+       list *lexps, *rexps = NULL, *exps;
 
        if (mvc_highwater(sql))
                return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: 
running out of stack space");
@@ -966,9 +966,14 @@ list *
        case op_full:
                lexps = _rel_projections(sql, rel->l, tname, settname, intern, 
basecol);
                exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
-               rexps = _rel_projections(sql, rel->r, tname, settname, intern, 
basecol);
+               if (!rel->attr)
+                       rexps = _rel_projections(sql, rel->r, tname, settname, 
intern, basecol);
                exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to