Changeset: 2e856c170afa for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2e856c170afa
Modified Files:
        sql/server/rel_optimize_sel.c
Branch: pp_hashjoin
Log Message:

when pushing down selects, we now try to push it to both sides if possible 
(using transitive info from the join).


diffs (90 lines):

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
@@ -1340,7 +1340,6 @@ push_up_join_exps( mvc *sql, sql_rel *re
        }
 }
 
-/* simple transitivity rule: a = b and b = c -> a = c */
 static sql_rel *
 transitivity_rule(visitor *v, sql_rel *rel)
 {
@@ -1666,7 +1665,7 @@ remove_blocking_selects( mvc *sql, sql_r
        case op_select:
                if (p) {
                        sql_rel *l = rel->l;
-                       if (is_single(rel) || !is_join(l->op))
+                       if (is_single(rel) || l->op != op_join)
                                return rel;
                        if (!list_empty(rel->exps)) {
                                p->exps = list_join(p->exps, rel->exps);
@@ -4642,6 +4641,49 @@ filter_column_in_partition_by_columns(sq
        return false;
 }
 
+/* transitivity rule on a = b and a = 'constant' => b = 'constant' */
+static void
+try_duplicate_select(visitor *v, sql_rel *r, sql_exp *e, bool leftside)
+{
+       if (!e || !r || e->type != e_cmp || e->flag != cmp_equal || is_anti(e) 
|| list_empty(r->exps) || rel_is_ref(r))
+               return;
+       sql_exp *el = e->l, *er = e->r;
+       if (!exp_is_atom(er))
+               return;
+       for (node *n = r->exps->h; n; n = n->next) {
+               sql_exp *je = n->data;
+
+               if (je->type == e_cmp && je->flag == cmp_equal && !is_anti(je)) 
{
+                       sql_exp *jel = je->l, *jer = je->r, *ne = NULL;
+                       if (jel->nid == el->nid) {
+                               if (!leftside && rel_rebind_exp(v->sql, r->r, 
jer)) /* check that jer is from right side */
+                                       ne = jer;
+                               if (leftside && rel_rebind_exp(v->sql, r->l, 
jer)) /* check that jer is from right side */
+                                       ne = jer;
+                       }
+                       if (jer->nid == el->nid) {
+                               if (!leftside && rel_rebind_exp(v->sql, r->r, 
jel)) /* check that jer is from right side */
+                                       ne = jel;
+                               if (leftside && rel_rebind_exp(v->sql, r->l, 
jel)) /* check that jer is from right side */
+                                       ne = jel;
+                       }
+                       if (ne) {
+                               ne = exp_compare(v->sql->sa, ne, er, cmp_equal);
+                               sql_rel *s = leftside ? r->l : r->r;
+                               if (!is_select(s->op)) {
+                                       if (leftside)
+                                               r->l = rel_select(v->sql->sa, 
s, ne);
+                                       else
+                                               r->r = rel_select(v->sql->sa, 
s, ne);
+                               } else {
+                                       rel_select_add_exp(v->sql->sa, s, ne);
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
 /*
  * Push select down, pushes the selects through (simple) projections. Also
  * it cleans up the projections which become useless.
@@ -4732,16 +4774,19 @@ rel_push_select_down(visitor *v, sql_rel
                        sql_exp *e = n->data;
 
                        if (!exp_unsafe(e, false, true)) {
+                               /* here we should also check if we need to 
duplicate the select expression the other side ! */
                                if (left && rel_rebind_exp(v->sql, jl, e)) {
                                        if (!is_select(jl->op) || 
rel_is_ref(jl))
                                                r->l = jl = 
rel_select(v->sql->sa, jl, NULL);
                                        rel_select_add_exp(v->sql->sa, jl, e);
+                                       try_duplicate_select(v, r, e, false);
                                        list_remove_node(exps, NULL, n);
                                        v->changes++;
                                } else if (right && rel_rebind_exp(v->sql, jr, 
e)) {
                                        if (!is_select(jr->op) || 
rel_is_ref(jr))
                                                r->r = jr = 
rel_select(v->sql->sa, jr, NULL);
                                        rel_select_add_exp(v->sql->sa, jr, e);
+                                       try_duplicate_select(v, r, e, true);
                                        list_remove_node(exps, NULL, n);
                                        v->changes++;
                                }
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to