Changeset: 245688022d44 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/245688022d44
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/rel_unnest.c
Branch: default
Log Message:

There's no need to have two optimizers to push inner join expressions down, 
also attempt to push expressions on left and right joins on the possible sides. 
Removed unused rel_has_cmp_exp function


diffs (265 lines):

diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -1546,21 +1546,6 @@ rel_has_all_exps(sql_rel *rel, list *exp
        return 1;
 }
 
-int
-rel_has_cmp_exp(sql_rel *rel, sql_exp *e)
-{
-       if (e->type == e_cmp) {
-               if (e->flag == cmp_or || e->flag == cmp_filter) {
-                       return rel_has_all_exps(rel, e->l) && 
rel_has_all_exps(rel, e->r);
-               } else if (e->flag == cmp_in || e->flag == cmp_notin) {
-                       return rel_has_exp(rel, e->l) == 0 && 
rel_has_all_exps(rel, e->r);
-               } else {
-                       return rel_has_exp(rel, e->l) == 0 && rel_has_exp(rel, 
e->r) == 0 && (!e->f || rel_has_exp(rel, e->f) == 0);
-               }
-       }
-       return 0;
-}
-
 sql_rel *
 find_rel(list *rels, sql_exp *e)
 {
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -174,8 +174,6 @@ extern int rel_has_exp(sql_rel *rel, sql
 extern int rel_has_exps(sql_rel *rel, list *e);
 /* return 1 when the relation contains all of the passed expressions else 0 */
 extern int rel_has_all_exps(sql_rel *rel, list *e);
-/* return 1 when the relation contains the expression else 0 */
-extern int rel_has_cmp_exp(sql_rel *rel, sql_exp *e);
 
 extern sql_rel *find_rel(list *rels, sql_exp *e);
 extern sql_rel *find_one_rel(list *rels, sql_exp *e);
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
@@ -4633,74 +4633,35 @@ rel_push_select_down(visitor *v, sql_rel
 }
 
 static inline sql_rel *
-rel_push_select_down_join(visitor *v, sql_rel *rel)
-{
-       list *exps = NULL;
-       sql_rel *r = NULL;
-       node *n;
-
-       exps = rel->exps;
-       r = rel->l;
-
-       /* push select through join */
-       if (/* DISABLES CODE */ (0) && is_select(rel->op) && exps && r && r->op 
== op_join && !(rel_is_ref(r))) {
-               rel->exps = new_exp_list(v->sql->sa);
-               for (n = exps->h; n; n = n->next) {
-                       sql_exp *e = n->data;
-                       if (e->type == e_cmp && !e->f && 
!is_complex_exp(e->flag)) {
-                               sql_rel *nr = NULL;
-                               sql_exp *re = e->r, *ne = rel_find_exp(r, re);
-
-                               if (ne && ne->card >= CARD_AGGR)
-                                       re->card = ne->card;
-
-                               if (re->card >= CARD_AGGR) {
-                                       nr = rel_push_join(v->sql, r, e->l, re, 
NULL, e, 0);
-                               } else {
-                                       nr = rel_push_select(v->sql, r, e->l, 
e, 0);
-                               }
-                               if (nr)
-                                       rel->l = nr;
-                               /* only pushed down selects are counted */
-                               if (r == rel->l) {
-                                       v->changes++;
-                               } else { /* Do not introduce an extra select */
-                                       sql_rel *r = rel->l;
-
-                                       rel->l = r->l;
-                                       r->l = NULL;
-                                       list_append(rel->exps, e);
-                                       rel_destroy(r);
-                               }
-                               assert(r == rel->l);
-                       } else {
-                               list_append(rel->exps, e);
-                       }
-               }
-               return rel;
-    /* push select exps part of the join expressions down */
-       } else if (is_innerjoin(rel->op) && !list_empty(exps)) {
-               for (n = exps->h; n;) {
+rel_push_join_exps_down(visitor *v, sql_rel *rel)
+{
+       /* push select exps part of join expressions down */
+       if ((is_innerjoin(rel->op) || is_left(rel->op) || is_right(rel->op) || 
is_semi(rel->op)) && !list_empty(rel->exps)) {
+               int left = is_innerjoin(rel->op) || is_right(rel->op) || 
is_semi(rel->op);
+               int right = is_innerjoin(rel->op) || is_left(rel->op) || 
is_semi(rel->op);
+
+               for (node *n = rel->exps->h; n;) {
                        node *next = n->next;
                        sql_exp *e = n->data;
 
-                       if (rel_rebind_exp(v->sql, rel->l, e)) {
+                       if (left && rel_rebind_exp(v->sql, rel->l, e)) { /* 
select expressions on left */
                                sql_rel *l = rel->l;
                                if (!is_select(l->op)) {
                                        set_processed(l);
                                        rel->l = l = rel_select(v->sql->sa, 
rel->l, NULL);
                                }
                                rel_select_add_exp(v->sql->sa, rel->l, e);
-                               list_remove_node(exps, NULL, n);
+                               list_remove_node(rel->exps, NULL, n);
                                v->changes++;
-                       } else if (rel_rebind_exp(v->sql, rel->r, e)) {
+                       } else if (right && (rel->op != op_anti || (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)) {
                                        set_processed(r);
                                        rel->r = r = rel_select(v->sql->sa, 
rel->r, NULL);
                                }
                                rel_select_add_exp(v->sql->sa, rel->r, e);
-                               list_remove_node(exps, NULL, n);
+                               list_remove_node(rel->exps, NULL, n);
                                v->changes++;
                        }
                        n = next;
@@ -4999,63 +4960,6 @@ rel_uses_part_nr( sql_rel *rel, sql_exp 
        return 0;
 }
 
-static sql_rel *
-rel_join_push_exps_down(visitor *v, sql_rel *rel)
-{
-       if (is_innerjoin(rel->op) || is_semi(rel->op)) {
-               sql_rel *l = rel->l, *r = rel->r;
-               list *lexps = NULL, *rexps = NULL;
-
-               if (list_empty(rel->exps))
-                       return rel;
-
-               for(node *n=rel->exps->h; n;) {
-                       node *next = n->next;
-                       sql_exp *e = n->data;
-                       int le = rel_has_cmp_exp(l, e), re = 0;
-
-                       if (!le && e->type == e_cmp && (rel->op != op_anti || 
(e->flag != mark_notin && e->flag != mark_in)))
-                               re = rel_has_cmp_exp(r, e);
-
-                       /* select expressions on left */
-                       if (le) {
-                               if (!lexps)
-                                       lexps=sa_list(v->sql->sa);
-                               append(lexps, e);
-                               v->changes++;
-                               list_remove_node(rel->exps, NULL, n);
-                       /* select expressions on right */
-                       } else if (re) {
-                               if (!rexps)
-                                       rexps=sa_list(v->sql->sa);
-                               append(rexps, e);
-                               v->changes++;
-                               list_remove_node(rel->exps, NULL, n);
-                       }
-                       n = next;
-               }
-               if (lexps) {
-                       if (is_select(l->op)) {
-                               l->exps = list_empty(l->exps) ? lexps : 
list_merge(l->exps, lexps, (fdup) NULL);
-                       } else {
-                               l = rel->l = rel_select(v->sql->sa, rel->l, 
NULL);
-                               l->exps = lexps;
-                       }
-               }
-               if (rexps) {
-                       if (is_select(r->op)) {
-                               r->exps = list_empty(r->exps) ? rexps : 
list_merge(r->exps, rexps, (fdup) NULL);
-                       } else {
-                               r = rel->r = rel_select(v->sql->sa, rel->r, 
NULL);
-                               r->exps = rexps;
-                       }
-               }
-               if (is_join(rel->op) && list_empty(rel->exps))
-                       rel->exps = NULL; /* crossproduct */
-       }
-       return rel;
-}
-
 /*
  * Push (semi)joins down unions, this is basically for merge tables, where
  * we know that the fk-indices are split over two clustered merge tables.
@@ -5399,7 +5303,7 @@ find_projection_for_join2semi(sql_rel *r
 }
 
 static sql_rel *
-find_candidate_join2semi(sql_rel *rel, bool *swap)
+find_candidate_join2semi(visitor *v, sql_rel *rel, bool *swap)
 {
        /* generalize possibility : we need the visitor 'step' here */
        if (rel_is_ref(rel)) /* if the join has multiple references, it's 
dangerous to convert it into a semijoin */
@@ -5422,7 +5326,7 @@ find_candidate_join2semi(sql_rel *rel, b
                        for (node *n=rel->exps->h; n && !ok; n = n->next) {
                                sql_exp *e = n->data;
 
-                               ok |= e->type == e_cmp && e->flag != cmp_or && 
!exp_has_func(e) && !rel_has_cmp_exp(l, e) && !rel_has_cmp_exp(r, e);
+                               ok |= e->type == e_cmp && e->flag != cmp_or && 
!exp_has_func(e) && !rel_rebind_exp(v->sql, l, e) && !rel_rebind_exp(v->sql, r, 
e);
                        }
                }
 
@@ -5432,12 +5336,12 @@ find_candidate_join2semi(sql_rel *rel, b
        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)
+               if ((c=find_candidate_join2semi(v, rel->l, swap)) != NULL ||
+                   (c=find_candidate_join2semi(v, rel->r, swap)) != NULL)
                        return c;
        }
        if (is_topn(rel->op) || is_sample(rel->op))
-               return find_candidate_join2semi(rel->l, swap);
+               return find_candidate_join2semi(v, rel->l, swap);
        return NULL;
 }
 
@@ -5482,7 +5386,7 @@ rel_join2semijoin(visitor *v, sql_rel *r
        if ((is_simple_project(rel->op) || is_groupby(rel->op)) && rel->l) {
                bool swap = false;
                sql_rel *l = rel->l;
-               sql_rel *c = find_candidate_join2semi(l, &swap);
+               sql_rel *c = find_candidate_join2semi(v, l, &swap);
 
                if (c) {
                        /* 'p' is a project */
@@ -9719,7 +9623,7 @@ rel_optimize_projections(visitor *v, sql
 static sql_rel *
 rel_optimize_joins(visitor *v, sql_rel *rel)
 {
-       rel = rel_push_select_down_join(v, rel);
+       rel = rel_push_join_exps_down(v, rel);
        rel = rel_out2inner(v, rel);
        rel = rel_join2semijoin(v, rel);
        rel = rel_push_join_down_outer(v, rel);
@@ -9846,8 +9750,6 @@ optimize_rel(mvc *sql, sql_rel *rel, int
                rel = rel_visitor_topdown(&v, rel, &rel_optimize_joins);
                if (!gp.cnt[op_update])
                        rel = rel_join_order(&v, rel);
-               if (level <= 0 && (gp.cnt[op_join] || gp.cnt[op_semi] || 
gp.cnt[op_anti]))
-                       rel = rel_visitor_bottomup(&v, rel, 
&rel_join_push_exps_down);
        }
 
        /* Important -> Re-write semijoins after rel_join_order */
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
@@ -2944,7 +2944,7 @@ rewrite_join2semi(visitor *v, sql_rel *r
                        /* If the left relation cannot hold the comparison it 
cannot be pushed to the semi(anti)-join
                           For now I guess only comparisons or anyequal func 
can appear here */
                        assert((is_func(e->type) && is_anyequal_func(sf)) || 
e->type == e_cmp);
-                       if ((is_func(e->type) && is_anyequal_func(sf)) || 
!rel_has_cmp_exp(j->l, e)) {
+                       if ((is_func(e->type) && is_anyequal_func(sf)) || 
!rel_rebind_exp(v->sql, j->l, e)) {
                                if (e->type == e_cmp) {
                                        append(j->exps, e);
                                } else {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to