Changeset: 6a6069579c30 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6a6069579c30
Modified Files:
        sql/server/rel_graph.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_rel.h
Branch: graph0
Log Message:

QRW: transform graph_select(A x B) into graph_join(A, B)


diffs (truncated from 403 to 300 lines):

diff --git a/sql/server/rel_graph.c b/sql/server/rel_graph.c
--- a/sql/server/rel_graph.c
+++ b/sql/server/rel_graph.c
@@ -91,21 +91,14 @@ sql_rel* rel_graph_reaches(mvc *sql, sql
     if(!qto) return NULL; // cannot convert qto into the same type of eto
 
     // build the new operator graph join operator
-    graph_ptr = (sql_graph*) sa_alloc(sql->sa, sizeof(sql_graph));
+    graph_ptr = rel_graph_create(sql->sa);
     if(!graph_ptr) { return sql_error(sql, 03, "Cannot allocate rel_graph"); }
-    memset(graph_ptr, 0, sizeof(sql_graph));
     result = (sql_rel*) graph_ptr;
-    sql_ref_init(&result->ref);
     result->op = op_graph_select;
     result->l = rel;
-    exp_ptr = (sql_exp*) sa_alloc(sql->sa, sizeof(sql_exp));
+    exp_ptr = exp_graph(sql, sa_list(sql->sa), sa_list(sql->sa));
     if(!exp_ptr) { return sql_error(sql, 03, "Cannot allocate sql_exp 
[e_graph] "); }
-    memset(exp_ptr, 0, sizeof(sql_exp));
-    exp_ptr->type = e_graph;
-    exp_ptr->card = CARD_MULTI;
-    exp_ptr->l = sa_list(sql->sa);
     list_append(exp_ptr->l, qfrom);
-    exp_ptr->r = sa_list(sql->sa);
     list_append(exp_ptr->r, qto);
     result->exps = sa_list(sql->sa); // by convention exps has to be a list, 
even it contains only one item
     list_append(result->exps, exp_ptr);
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
@@ -1364,8 +1364,14 @@ static sql_exp *
        case e_atom:
        case e_psm:
                return e;
-       case e_graph:
-               assert(0 && "Not implemented yet");
+       case e_graph: {
+               list *lst1 = NULL, *lst2 = NULL;
+               lst1 = exps_push_down(sql, e->l, f, t);
+               if(list_empty(lst1)) return NULL;
+               lst2 = exps_push_down(sql, e->r, f, t);
+               if(list_empty(lst2)) return NULL;
+               return exp_graph(sql, lst1, lst2);
+       } break;
        }
        return NULL;
 }
@@ -8435,7 +8441,6 @@ rel_apply_rewrite(int *changes, mvc *sql
        }
        if (rel->flag == APPLY_LOJ && r->op == op_select) {
                sql_rel *nr, *ns;
-
                nr = rel_project(sql->sa, rel_dup(r), 
                        rel_projections(sql, r, NULL, 1, 1));
                ns = rel_apply(sql, rel_dup(rel->l), nr, rel->exps, rel->flag);
@@ -8629,6 +8634,168 @@ rel_apply_rewrite(int *changes, mvc *sql
 }
 
 static sql_rel *
+rel_graph_pda(int *changes, mvc *sql, sql_rel *rel)
+{
+       sql_rel* graph_rel = rel;
+       sql_rel* parent = NULL;
+       sql_rel* target = NULL;
+       sql_exp* graph_pda = NULL;
+
+       // only applies to op_graph_select
+       if(graph_rel->op != op_graph_select) {
+               return rel;
+       }
+       graph_pda = graph_rel->exps->h->data;
+       assert(graph_pda != NULL && "Interesting, here we have a graph select 
without a predicate...");
+       assert(graph_pda->type == e_graph);
+
+       target = parent = rel->l;
+
+       // pass through selects
+       if(target->op == op_select){
+               target = target->l;
+       }
+
+       // do not cross references
+       if(rel_is_ref(target) || rel_is_ref(parent))
+               return rel;
+
+       // ref cnt
+       printf("[rel_graph_pda] cnt: %d\n", graph_rel->ref.refcnt);
+
+       // case 1 - try to push down through a join or another graph operator
+       if(is_join(target->op) || is_graph(target->op)){
+               sql_rel* l = target->l;
+               sql_rel* r = target->r;
+               sql_exp* ne = NULL;
+               bool pda_lhs = true; // otherwise go to the right
+
+               // can we push down to the lhs or rhs of the join?
+               bool left = r->op == op_join || r->op == op_left || r->op == 
op_graph_join || r->op == op_graph_select;
+               bool right = r->op == op_join || r->op == op_right || r->op == 
op_graph_join;
+
+               // push down to the lhs
+               if (left){
+                       ne = exp_push_down(sql, graph_pda, l, l);
+               }
+               // try to push to the rhs
+               if (!ne && right) {
+                       pda_lhs = false;
+                       ne = exp_push_down(sql, graph_pda, r, r);
+               }
+
+               // success?
+               if (ne) {
+                       list_remove_node(graph_rel->exps, graph_rel->exps->h);
+                       assert(list_empty(graph_rel->exps));
+                       list_append(graph_rel->exps, ne);
+
+                       // reshape the tree
+                       if (pda_lhs){
+                               graph_rel->l = target->l;
+                               target->l = graph_rel;
+                       } else {
+                               graph_rel->l = target->r;
+                               target->r = graph_rel;
+                       }
+
+                       (*changes)++;
+                       return parent;
+               }
+       }
+
+       return rel;
+}
+
+static sql_rel *
+rel_graph_create_join(int *changes, mvc *sql, sql_rel *rel)
+{
+       sql_rel* graph_rel = rel;
+       sql_rel* parent = NULL;
+       sql_rel* target = NULL;
+       sql_exp* graph_pda = NULL;
+
+       // only applies to op_graph_select
+       if(graph_rel->op != op_graph_select || rel_is_ref(rel)) {
+               return rel;
+       }
+       graph_pda = graph_rel->exps->h->data;
+       assert(graph_pda != NULL && "Interesting, here we have a graph select 
without a predicate...");
+       assert(graph_pda->type == e_graph);
+
+       target = rel->l;
+
+       // pass through selects
+       if(target->op == op_select){
+               parent = target;
+               target = target->l;
+       }
+
+       // do not cross references
+       if(rel_is_ref(target) || (parent && rel_is_ref(parent)))
+               return rel;
+
+       // check the parent is a cross product
+       if(target->op == op_join && list_empty(target->exps)){
+               sql_rel *l = target->l;
+               sql_rel *r = target->r;
+               bool order_lhs = true; // otherwise go the left hand side
+               list *el = NULL;
+               list *er = NULL;
+
+               // bind to the lhs
+               el = exps_push_down(sql, graph_pda->l, l, l);
+               if(!el){ // ok that didn't work out, try with the rhs
+                       order_lhs = false;
+                       el = exps_push_down(sql, graph_pda->l, r, r);
+               }
+
+               // if we did bind the lhs above, then we are guaranteed that the
+               // rhs will bind as well. Otherwise we are in the case where
+               // the rule `rel_graph_pda' would have move this operator above
+               // this cross product.
+               if(el){
+                       sql_exp* ne = NULL; // construct the new e_graph 
expression (jic)
+
+                       if(order_lhs){
+                               er = exps_push_down(sql, graph_pda->r, r, r);
+                       } else {
+                               er = exps_push_down(sql, graph_pda->r, l, l);
+                       }
+                       assert(er != NULL && "See comment in the code above");
+                       ne = exp_graph(sql, el, er);
+
+                       // replace the cross product with a graph_join
+                       rel_destroy(target);
+                       target = (sql_rel*) rel_graph_create(sql->sa);
+                   memcpy(target, graph_rel, sizeof(sql_graph));
+                   target->op = op_graph_join;
+                   target->exps = new_exp_list(sql->sa);
+                   list_append(target->exps, ne);
+                   target->l = l;
+                   target->r = r;
+
+                   // replace the graph_select with a dummy operator
+                   graph_rel->op = op_select;
+                   graph_rel->exps = new_exp_list(sql->sa);
+                   graph_rel->p = NULL;
+
+                   // update the parent
+                   if(parent){
+                       parent->l = target;
+                       parent->nrcols = target->nrcols;
+                   } else {
+                       graph_rel->l = target;
+                   }
+
+                   (*changes)++;
+               }
+       }
+
+       return rel;
+}
+
+static sql_rel *
 rewrite(mvc *sql, sql_rel *rel, rewrite_fptr rewriter, int *has_changes) 
 {
        int changes = 0;
@@ -8753,6 +8920,7 @@ static sql_rel *
 _rel_optimizer(mvc *sql, sql_rel *rel, int level) 
 {
        int changes = 0, e_changes = 0;
+       bool graph_operators = false;
        global_props gp; 
 
        memset(&gp, 0, sizeof(global_props));
@@ -8768,6 +8936,9 @@ static sql_rel *
 }
 #endif
 
+       // do we have any graph operators around?
+       graph_operators = gp.cnt[op_graph_select] || gp.cnt[op_graph_join];
+
        /* simple merging of projects */
        if (gp.cnt[op_project] || gp.cnt[op_ddl]) {
                rel = rewrite(sql, rel, &rel_merge_projects, &changes);
@@ -8839,6 +9010,16 @@ static sql_rel *
                rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); 
        }
 
+       if (graph_operators){
+               rel = rewrite_topdown(sql, rel, rel_graph_pda, &changes);
+               printf("[Optimizer] rel_graph_pda: %s\n", dump_rel(sql, rel));
+               rel = rewrite_topdown(sql, rel, rel_graph_create_join, 
&changes);
+               printf("[Optimizer] rel_graph_create_join: %s\n", dump_rel(sql, 
rel));
+               // rel_graph_create_join creates empty (dummy) selects
+               rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes);
+               printf("[Optimizer] rel_remove_empty_select: %s\n", 
dump_rel(sql, rel));
+       }
+
        if (gp.cnt[op_select] && gp.cnt[op_join]) {
                rel = rewrite_topdown(sql, rel, &rel_push_select_down_join, 
&changes); 
                rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); 
@@ -8871,6 +9052,8 @@ static sql_rel *
                rel = rewrite(sql, rel, &rel_groupby_distinct, &changes); 
        }
 
+
+       printf("[Optimizer] rel_join_order before: %s\n", dump_rel(sql, rel));
        if (gp.cnt[op_join] || gp.cnt[op_left] || gp.cnt[op_semi] || 
gp.cnt[op_anti]) {
                rel = rel_remove_empty_join(sql, rel, &changes);
                if (!gp.cnt[op_update])
@@ -8879,6 +9062,7 @@ static sql_rel *
                /* rel_join_order may introduce empty selects */
                rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); 
        }
+       printf("[Optimizer] rel_join_order after: %s\n", dump_rel(sql, rel));
 
        if (gp.cnt[op_select] && sql->emode != m_prepare) 
                rel = rewrite(sql, rel, &rel_simplify_like_select, &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
@@ -100,6 +100,16 @@ rel_create( sql_allocator *sa )
        return r;
 }
 
+sql_graph*
+rel_graph_create( sql_allocator *sa )
+{
+       sql_graph *r = SA_NEW(sa, sql_graph);
+       if(!r) return NULL;
+       memset(r, 0, sizeof(sql_graph));
+       sql_ref_init(&(r->relation.ref));
+       return r;
+}
+
 sql_rel *
 rel_copy( sql_allocator *sa, sql_rel *i )
 {
@@ -178,12 +188,15 @@ rel_bind_column_(mvc *sql, sql_rel **p, 
 {
        int ambiguous = 0;
        sql_rel *l = NULL, *r = NULL;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to