Changeset: c942d8b7c404 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c942d8b7c404
Modified Files:
        sql/common/sql_types.c
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_graph.c
        sql/server/rel_graph.h
        sql/server/rel_optimizer.c
Branch: graph0
Log Message:

QRW: fix DCE for nested tables

Propagate the attributes removed by the DCE pass up to the generator
expression. Still need to be fixed for SYS.NEST(...)


diffs (truncated from 401 to 300 lines):

diff --git a/sql/common/sql_types.c b/sql/common/sql_types.c
--- a/sql/common/sql_types.c
+++ b/sql/common/sql_types.c
@@ -906,11 +906,8 @@ sql_bind_func_(sql_allocator *sa, sql_sc
                if (f->type != type && f->type != filt) 
                        continue;
                if (strcmp(f->base.name, sqlfname) == 0) {
-                       printf("match %s\n", f->base.name);
-                       if (list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 
0) {
-                               printf("found\n");
+                       if (list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0)
                                return sql_dup_subfunc(sa, f, ops, NULL);
-                       }
                }
        }
        if (s) {
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
@@ -538,7 +538,7 @@ rel_print_(mvc *sql, stream  *fout, sql_
        case op_graph_select: {
                sql_graph *graph_ptr = (sql_graph*) rel;
                print_indent(sql, fout, depth, decorate);
-               mnstr_printf(fout, "%s", op2string(rel->op));
+               mnstr_printf(fout, "%s (", op2string(rel->op));
                if (rel_is_ref(rel->l)) {
                        int nr = find_ref(refs, rel->l);
                        print_indent(sql, fout, depth+1, decorate);
@@ -562,14 +562,15 @@ rel_print_(mvc *sql, stream  *fout, sql_
                        rel_print_(sql, fout, graph_ptr->edges, depth+1, refs, 
decorate);
                }
                print_indent(sql, fout, depth, decorate);
+               mnstr_printf(fout, ")");
                exps_print(sql, fout, rel->exps, depth, 1, 0);
                mnstr_printf(fout, ", src:");
                exps_print(sql, fout, graph_ptr->efrom, depth, 1, 0);
                mnstr_printf(fout, ", dst:");
                exps_print(sql, fout, graph_ptr->eto, depth, 1, 0);
                print_indent(sql, fout, depth, decorate);
-               mnstr_printf(fout, "shortest paths: ");
-               exps_print(sql, fout, graph_ptr->spfw, depth, 1, 1);
+               mnstr_printf(fout, "π :");
+               exps_print(sql, fout, graph_ptr->spfw, depth, 1, 0);
        }   break;
        default:
                assert(0);
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
@@ -9,6 +9,7 @@
 #include <monetdb_config.h>
 #include "sql_relation.h"
 #include "rel_exp.h"
+#include "rel_graph.h"
 #include "rel_prop.h" /* for prop_copy() */
 #include "rel_optimizer.h"
 #include "rel_distribute.h"
@@ -1274,6 +1275,7 @@ rel_find_exp_( sql_rel *rel, sql_exp *e)
                // check whether this is some kind of shortest path
                else if (is_graph(rel->op) && e->l){
                        sql_graph* graph_ptr = (sql_graph*) rel;
+//                     ne = graph_bind_spfw(rel, e->l, e->r);
                        ne = exps_bind_column2(graph_ptr->spfw, e->l, e->r);
                }
                return ne;
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
@@ -281,6 +281,11 @@ static list* bind_shortest_path_graph(mv
                                assert(type != NULL && "Cannot find the 
'nested_table' type");
                                // record the columns composing the 
nested_table type, from the edge table
                                type->attributes = exps_copy(sql->sa, 
rel_projections(sql, edges, NULL, /* settname = */ true, /* intern = */ false));
+                               // set the relation name to label
+                               for(node* n = type->attributes->h; n; n = 
n->next){
+                                       sql_exp* ne = n->data;
+                                       ne->rname = label;
+                               }
 
                                column_path = exp_column(sql->sa, label, label, 
type, CARD_MULTI, /* has_nil = */ FALSE, /* is_intern = */ FALSE);
                                column_path->flag |= GRAPH_EXPR_SHORTEST_PATH;
@@ -369,3 +374,48 @@ list* rel_graph_shortest_path(mvc *sql, 
                return result; // this can be an exp~ or NULL + an error set
        }
 }
+
+
+/*****************************************************************************
+ *                                                                           *
+ * Bind an expression produced by a graph operator                           *
+ *                                                                           *
+ *****************************************************************************/
+// Attempt to bind the column with table name `tbl_name' and column name 
`col_name'
+// to one of the expression generated by the graph operator (i.e. a shortest 
path).
+// It returns the expression bound if found, NULL otherwise.
+sql_exp* graph_bind_spfw(sql_rel* rel, const char* tbl_name, const char* 
col_name){
+       sql_graph* graph_ptr = NULL;
+
+       assert(rel && is_graph(rel->op) && "The given operator is not a graph");
+       graph_ptr = (sql_graph*) rel;
+
+       // all expressions associated to a graph operator need to have a table 
name
+       if(!tbl_name) return NULL;
+
+       for(node* n = graph_ptr->spfw->h; n; n = n->next){
+               sql_exp* candidate = n->data;
+
+               if(candidate->flag & GRAPH_EXPR_COST){
+                       if(strcmp(tbl_name, candidate->rname) == 0 && 
strcmp(col_name, candidate->name) == 0){
+                               return candidate;
+                       }
+               } else if (candidate->flag & GRAPH_EXPR_SHORTEST_PATH){
+                       assert(candidate->type == e_column && "Paths should be 
columns");
+                       if(strcmp(tbl_name, candidate->rname) == 0){
+                               assert(candidate->tpe.type->eclass == 
EC_NESTED_TABLE && "Expected a nested table (class)");
+                               assert(candidate->tpe.attributes != NULL && 
"Expected a nested table (attrs)");
+                               if(strcmp(col_name, candidate->name) == 0){ // 
fetch the nested table
+                                       return candidate;
+                               }
+
+                               candidate = 
exps_bind_column(candidate->tpe.attributes, col_name, NULL);
+                               assert(candidate != NULL && "How was it able to 
match the table name and not the column name?");
+                               return candidate;
+                       }
+               }
+       }
+
+       // not found
+       return NULL;
+}
diff --git a/sql/server/rel_graph.h b/sql/server/rel_graph.h
--- a/sql/server/rel_graph.h
+++ b/sql/server/rel_graph.h
@@ -19,4 +19,6 @@ sql_graph* rel_graph_create(sql_allocato
 sql_graph* rel_graph_move(mvc* sql, sql_rel* graph_old, sql_rel* l, sql_rel* 
r, sql_exp* e);
 sql_rel* rel_graph_move2rel(mvc* sql, sql_rel* graph_old, sql_rel* l, sql_rel* 
r, sql_exp* e);
 
+sql_exp* graph_bind_spfw(sql_rel* rel, const char* relname, const char* 
colname);
+
 #endif /* _REL_GRAPH_H_ */
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
@@ -5987,6 +5987,74 @@ rel_push_project_up(int *changes, mvc *s
        return rel;
 }
 
+
+static void
+exp_nested_table_mark_used(sql_exp* exp_up, sql_exp* exp_down){
+       sql_exp* exp_nest = NULL; // the summary sys.nest( ... )
+       sql_exp* exp_unnest = NULL;
+       list* used_attributes = NULL;
+       list* target_attributes = NULL;
+//     list* new_attributes = NULL;
+
+       assert(exp_up != NULL && exp_down != NULL);
+
+       if(exp_up->type == e_cmp && get_cmp(exp_up) == cmp_unnest){
+               exp_unnest = exp_up;
+               exp_up = exp_unnest->l;
+       } else {
+               assert(exp_up->type == e_column);
+       }
+
+       if(exp_down->type == e_aggr /*&& exp_nest->f ~ "sys.nest"*/){
+               sql_subaggr* subaggr = exp_down->f;
+               sql_subtype* type = subaggr->res->h->data;
+               assert(type->attributes != NULL);
+
+               exp_nest = exp_down;
+               target_attributes = type->attributes;
+       } else {
+               assert(exp_down->type == e_column);
+               target_attributes = exp_down->tpe.attributes;
+       }
+
+       assert(exp_up->tpe.attributes != NULL);
+       assert(exp_down->tpe.attributes != NULL);
+
+       if(exp_unnest){
+               used_attributes = exp_unnest->r;
+       } else {
+               used_attributes = exp_up->tpe.attributes;
+       }
+
+       // mark the sub type
+//     new_attributes = sa_list(used_attributes->sa);
+       for(node* m = used_attributes->h; m; m = m->next){
+               sql_exp* attribute = m->data;
+               sql_exp* target = NULL;
+
+               assert(attribute->type == e_column);
+               if(!attribute->used) continue;
+               if(exp_nest){
+                       target = exps_bind_column2(target_attributes, 
attribute->l, attribute->r);
+               } else {
+                       target = exps_bind_column2(target_attributes, 
attribute->rname, attribute->name);
+               }
+
+
+               assert(target != NULL && target->type == e_column);
+               target->used = 1;
+//             list_append(new_attributes, target);
+       }
+
+//     exp_down->tpe.attributes = new_attributes;
+//     if(exp_unnest){
+//             exp_up->tpe.attributes = new_attributes;
+//     }
+       if(exp_unnest){
+               exp_up->tpe.attributes = exp_unnest->tpe.attributes;
+       }
+}
+
 static int
 exp_mark_used(sql_rel *subrel, sql_exp *e)
 {
@@ -5996,6 +6064,9 @@ exp_mark_used(sql_rel *subrel, sql_exp *
        switch(e->type) {
        case e_column:
                ne = rel_find_exp(subrel, e);
+               if(e && ne && e->tpe.type->eclass == EC_NESTED_TABLE){
+                       exp_nested_table_mark_used(e, ne);
+               }
                break;
        case e_convert:
                return exp_mark_used(subrel, e->l);
@@ -6021,8 +6092,10 @@ exp_mark_used(sql_rel *subrel, sql_exp *
                        for (n = l->h; n != NULL; n = n->next) 
                                nr += exp_mark_used(subrel, n->data);
                } else if (e->flag == cmp_unnest) {
-                       nr += exp_mark_used(subrel, e->l);
-                       // do not mark the attributes here
+                       sql_exp* column = e->l;
+                       assert(column->type == e_column && "Expected a column 
in the LHS of an unnest expression");
+                       ne = rel_find_exp(subrel, column);
+                       exp_nested_table_mark_used(e, ne);
                } else if (e->flag == cmp_in || e->flag == cmp_notin) {
                        list *r = e->r;
                        node *n;
@@ -6302,8 +6375,34 @@ rel_mark_used(mvc *sql, sql_rel *rel, in
                // edges
                exps_mark_used_(sql->sa, rel, graph_ptr->edges, 
graph_ptr->efrom);
                exps_mark_used_(sql->sa, rel, graph_ptr->edges, graph_ptr->eto);
-               exps_mark_used_(sql->sa, rel, graph_ptr->edges, 
graph_ptr->spfw);
-
+//             exps_mark_used_(sql->sa, rel, graph_ptr->edges, 
graph_ptr->spfw);
+               // shortest paths
+               for(node* n = graph_ptr->spfw->h; n; n = n->next){
+                       sql_exp* e = n->data;
+                       if(e->flag & GRAPH_EXPR_COST){
+                               exp_mark_used(graph_ptr->edges, e);
+                       } else if(e->flag & GRAPH_EXPR_SHORTEST_PATH){
+                               int nr = 0;
+
+                               assert(e->tpe.attributes != NULL && "Expected a 
nested table as type");
+                               for(node* m = e->tpe.attributes->h; m; m = 
m->next){
+                                       sql_exp* me = m->data;
+                                       // since unnest is not a barrier in the 
DCE analysis, we need to explicitly
+                                       // check whether the attribute has been 
marked earlier
+                                       if(me->used){
+                                               nr++;
+                                               exp_mark_used(graph_ptr->edges, 
e);
+                                       }
+                               }
+                               if(nr == list_length(e->tpe.attributes)){
+                                       e->used = 1;
+                               }
+                       } else {
+                               assert(0 && "Invalid graph expression");
+                       }
+               }
+
+               // this should be a nop because graph_ptr->edges should be a 
projection
                rel_mark_used(sql, graph_ptr->edges, 0);
        } break;
        }
@@ -6373,9 +6472,31 @@ rel_remove_unused(mvc *sql, sql_rel *rel
 
                        for(n=rel->exps->h; n && !needed; n = n->next) {
                                sql_exp *e = n->data;
+                               list* nt_attributes = NULL; // nested table 
attributes
 
                                if (!e->used)
                                        needed = 1;
+
+                               // nested tables
+                               else if(e->type == e_column){
+                                       nt_attributes = e->tpe.attributes;
+                               } else if (e->type == e_aggr) { // sys.nest()
+                                       sql_subaggr* aggr = e->f;
+                                       sql_subtype* type = NULL;
+                                       if(list_length(aggr->res) == 1){
+                                               type = aggr->res->h->data;
+                                               nt_attributes = 
type->attributes;
+                                       }
+                               }
+                               if (nt_attributes){ // a bit of spaghetti :D
+                                       for (node *m = nt_attributes->h; m && 
!needed; m = m->next){
+                                               sql_exp* me = m->data;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to