Changeset: 403d0b7e036f for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=403d0b7e036f
Modified Files:
        monetdb5/modules/atoms/nested_table.c
        monetdb5/modules/atoms/nested_table.mal
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
        sql/server/rel_select.c
Branch: graph0
Log Message:

CODEGEN: unnest


diffs (truncated from 327 to 300 lines):

diff --git a/monetdb5/modules/atoms/nested_table.c 
b/monetdb5/modules/atoms/nested_table.c
--- a/monetdb5/modules/atoms/nested_table.c
+++ b/monetdb5/modules/atoms/nested_table.c
@@ -25,6 +25,7 @@
 
 // prototypes
 mal_export str NESTEDTABLEnest1_oid(bat*, const bat*, const bat*);
+mal_export str NESTEDTABLEunnest101_oid(bat*, bat*, const bat*);
 mal_export str NESTEDTABLEprelude(void*);
 
 // index in the BATatoms table
@@ -104,6 +105,7 @@ mal_export str NESTEDTABLEnest1_oid(bat*
        oid pos = ++output_content[count];
        output_content[pos] = i;
     }
+    group_mapping->tvheap->free = sum * sizeof(oid);
 
 success:
        BBPunfix(group_mapping->batCacheid);
@@ -121,3 +123,61 @@ error:
        return rc;
 }
 
+mal_export str NESTEDTABLEunnest101_oid(bat* out_jl, bat* out_jr, const bat* 
in_nested_attribute){
+       const char* function_name = "nestedtable.unnest1";
+       str rc = MAL_SUCCEED;
+       BAT *nested_attribute = NULL;
+       var_t* __restrict na_offsets = NULL;
+       oid* __restrict na_values = NULL;
+       oid na_count = 0;
+       BAT *jl = NULL, *jr = NULL;
+
+       // input argument
+       CHECK(in_nested_attribute != NULL, ILLEGAL_ARGUMENT);
+       nested_attribute = BATdescriptor(*in_nested_attribute);
+       CHECK(nested_attribute != NULL, RUNTIME_OBJECT_MISSING);
+       CHECK(ATOMtype(nested_attribute->ttype) == TYPE_nested_table, 
ILLEGAL_ARGUMENT);
+
+       // output arguments
+       assert(nested_attribute->hseqbase == 0 && "Partition unexpected");
+       jl = COLnew(nested_attribute->hseqbase, TYPE_oid, 
BATcount(nested_attribute) * 5, TRANSIENT); // *5 <= arbitrary value
+       jr = COLnew(nested_attribute->hseqbase, TYPE_oid, 
BATcount(nested_attribute) * 5, TRANSIENT);
+       CHECK(jl != NULL && jr != NULL, MAL_MALLOC_FAIL);
+
+       // empty argument?
+       na_count = BATcount(nested_attribute);
+       if(na_count == 0) goto success; // skip here as the vheap may not be 
effectively allocated
+
+       na_offsets = (var_t*) nested_attribute->T.heap.base;
+       assert(nested_attribute->T.vheap != NULL);
+       na_values = (oid*) nested_attribute->T.vheap->base;
+       for(oid i = 0; i < na_count; i++){
+               var_t offset = na_offsets[i];
+               oid* __restrict base = na_values + offset;
+               oid off_count = *(base++);
+               assert(((offset+off_count) * sizeof(oid) <= 
nested_attribute->T.vheap->size) && "Index out of bounds");
+               for(oid j = 0; j < off_count; j++){
+                       BUNappend(jl, &i, false);
+               }
+               for(oid j = 0; j < off_count; j++){
+                       oid off_value = base[j];
+                       BUNappend(jr, &off_value, false);
+               }
+       }
+
+success:
+       BBPunfix(nested_attribute->batCacheid);
+       *out_jl = jl->batCacheid;
+       BBPkeepref(jl->batCacheid);
+       *out_jr = jr->batCacheid;
+       BBPkeepref(jr->batCacheid);
+
+       return rc;
+error:
+       if(nested_attribute){ BBPunfix(nested_attribute->batCacheid); }
+       if(jl){ BBPunfix(jl->batCacheid); }
+       if(jr){ BBPunfix(jr->batCacheid); }
+
+       return rc;
+}
+
diff --git a/monetdb5/modules/atoms/nested_table.mal 
b/monetdb5/modules/atoms/nested_table.mal
--- a/monetdb5/modules/atoms/nested_table.mal
+++ b/monetdb5/modules/atoms/nested_table.mal
@@ -14,5 +14,9 @@ command nest1(group_mapping :bat[:oid], 
 address NESTEDTABLEnest1_oid
 comment "Create a nested table out of the grouped partitions";
 
+command unnest1(:bat[:nestedtable]) (:bat[:oid], :bat[:oid])
+address NESTEDTABLEunnest101_oid
+comment "Extract the candidate list from a nested table"
+
 # Initialize
 nestedtable.prelude();
\ No newline at end of file
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
@@ -23,6 +23,7 @@
 static stmt * exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt 
*grp, stmt *ext, stmt *cnt, stmt *sel);
 static stmt * rel_bin(backend *be, sql_rel *rel);
 static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs);
+static stmt * stmt_rename(backend *be, sql_rel *rel, sql_exp *exp, stmt *s);
 
 static stmt *
 refs_find_rel(list *refs, sql_rel *rel)
@@ -528,8 +529,8 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                        node *n;
                        int first = 1;
 
-                       ops = sa_list(sql->sa);
-                       args = e->l;
+                       ops = sa_list(sql->sa);
+                       args = e->l;
                        for( n = args->h; n; n = n->next ) {
                                s = NULL;
                                if (!swapped)
@@ -563,6 +564,36 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                        assert(!swapped);
                        s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
                        return s;
+               } else if (get_cmp(e) == cmp_unnest){
+                       sql_exp* lhs = e->l;
+                       list* rhs = e->r;
+                       list* na_list = NULL;
+                       list* expanded_attributes = sa_list(sql->sa);
+
+                       // find the column to unnest
+                       assert(lhs->type == e_column && "The attribute to 
'unnest' is not a column");
+                       l = bin_find_column(be, left, lhs->l, lhs->r);
+                       assert(l != NULL && "Unable to bind the column to 
unnest");
+                       if(!l) return NULL; // error
+
+                       // the nested attributes
+                       assert(list_length(rhs) != 0 && "No attributes to 
expand");
+//                     na_list = l->op4.lval;
+                       na_list = list_nested_attributes(l);
+                       assert(na_list != NULL && "Empty list of nested 
attributes. Have the list of attributes been propagated?");
+                       for(node *n = rhs->h; n; n = n->next){
+                               sql_exp* e = n->data;
+                               assert(e->type == e_column && "The attribute 
being expanded is not a column");
+//                             r = bin_find_column(be, l, e->l, e->r);
+                               r = list_find_column(be, na_list, e->l, e->r);
+                               assert(r != NULL && "Unable to bind the nested 
column");
+                               if(!r) return NULL; // error
+                               r = stmt_rename(be, NULL, e, r);
+                               list_append(expanded_attributes, r);
+                       }
+                       r = stmt_list(be, expanded_attributes);
+
+                       return stmt_unnest(be, l, r);
                }
                if (e->flag == cmp_in || e->flag == cmp_notin) {
                        return handle_in_exps(be, e->l, e->r, left, right, grp, 
ext, cnt, sel, (e->flag == cmp_in), 0);
@@ -2787,6 +2818,56 @@ rel2bin_sample(backend *be, sql_rel *rel
        return sub;
 }
 
+static stmt *
+rel2bin_unnest(backend *be, sql_rel *rel, list *refs){
+       stmt *sub = NULL;
+       sql_exp *unnest_expr;
+       stmt *unnest = NULL;
+       stmt *nested_attribute = NULL;
+       stmt *unnest_lhs = NULL;
+       stmt *unnest_rhs = NULL;
+       list *output_columns = NULL;
+
+       // build the subrelation first
+       assert(rel->l != NULL && "Unnest operator with no input relation");
+       sub = subrel_bin(be, rel->l, refs);
+       if(!sub) return NULL;
+
+       // create the candidate list of the attributes to project
+       assert(list_length(rel->exps) == 1 && "Expected a single expression");
+       unnest_expr = rel->exps->h->data;
+       assert(unnest_expr->type == e_cmp && get_cmp(unnest_expr) == 
cmp_unnest);
+       unnest = exp_bin(be, unnest_expr, sub, NULL, NULL, NULL, NULL, NULL);
+       assert(unnest != NULL && "No output from the `unnest' predicate");
+       nested_attribute = unnest->op1;
+       unnest_lhs = stmt_result(be, unnest, 0);
+       unnest_rhs = stmt_result(be, unnest, 1);
+
+       // project back the attributes from the input relation except the 
column representing the nested table
+       assert(sub->type == st_list);
+       output_columns = sa_list(be->mvc->sa);
+       for(node* n = sub->op4.lval->h; n; n = n->next){
+               stmt* c = column(be, n->data);
+               const char *tname = NULL, *cname = NULL; // damn C90
+               if(c == nested_attribute) continue;
+               tname = table_name(be->mvc->sa, c);
+               cname = column_name(be->mvc->sa, c);
+               c = stmt_project(be, unnest_lhs, c);
+               list_append(output_columns, stmt_alias(be, c, tname, cname));
+       }
+
+       // project the nested attributes
+       for(node* n = unnest->op4.lval->h; n; n = n->next){
+               stmt* c = column(be, n->data);
+               const char *tname = table_name(be->mvc->sa, c);
+               const char *cname = column_name(be->mvc->sa, c);
+               c = stmt_project(be, unnest_rhs, c);
+               list_append(output_columns, stmt_alias(be, c, tname, cname));
+       }
+
+       return stmt_list(be, output_columns);
+}
+
 stmt *
 sql_parse(backend *be, sql_allocator *sa, char *query, char mode)
 {
@@ -4773,7 +4854,8 @@ subrel_bin(backend *be, sql_rel *rel, li
                sql->type = Q_TABLE;
                break;
        case op_unnest:
-               assert("Not handled yet");
+               s = rel2bin_unnest(be, rel, refs);
+               sql->type = Q_TABLE;
                break;
        case op_insert: 
                s = rel2bin_insert(be, rel, refs);
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
@@ -1817,6 +1817,7 @@ stmt_project(backend *be, stmt *op1, stm
 
                s->op1 = op1;
                s->op2 = op2;
+               s->op4.lval = list_nested_attributes(s->op2);
                s->flag = cmp_project;
                s->key = 0;
                s->nrcols = 2;
@@ -2912,6 +2913,28 @@ stmt *stmt_nest(backend *be, stmt *ops, 
 
 }
 
+stmt *stmt_unnest(backend *be, stmt *nested_attribute, stmt* list_operands){
+       InstrPtr q = NULL;
+       stmt* s = NULL;
+
+       q = newStmt(be->mb, "nestedtable", "unnest1");
+       getArg(q, 0) = newTmpVariable(be->mb, TYPE_bat);
+       q = pushReturn(be->mb, q, newTmpVariable(be->mb, TYPE_bat));
+       assert(nested_attribute != NULL && nested_attribute->nr > 0);
+       q = pushArgument(be->mb, q, nested_attribute->nr);
+
+       if(q){
+               s = stmt_create(be->mvc->sa, st_unnest);
+               s->op1 = nested_attribute;
+               s->op4.lval = list_operands->op4.lval;
+               s->nrcols = list_length(s->op4.lval) + 2;
+               s->nr = getDestVar(q);
+               s->q = q;
+       }
+
+       return s;
+}
+
 static stmt *
 stmt_alias_(backend *be, stmt *op1, const char *tname, const char *alias)
 {
@@ -3503,3 +3526,25 @@ const_column(backend *be, stmt *val)
        }
        return NULL;
 }
+
+
+list *list_nested_attributes(stmt* st){
+       assert(st != NULL);
+       switch(st->type){
+       case st_aggr:
+               if(st->op1->type == st_list){
+                       return st->op1->op4.lval;
+               }
+               break;
+       case st_alias:
+               return list_nested_attributes(st->op1);
+       case st_join:
+               return st->op4.lval;
+       case st_rs_column:
+               return NULL;
+       default:
+               assert(0 && "Statement type not handled");
+       }
+
+       return NULL;
+}
diff --git a/sql/backends/monet5/sql_statement.h 
b/sql/backends/monet5/sql_statement.h
--- a/sql/backends/monet5/sql_statement.h
+++ b/sql/backends/monet5/sql_statement.h
@@ -85,6 +85,7 @@ typedef enum stmt_type {
        st_Nop,
        st_func,
        st_aggr,
+       st_unnest,
 
        st_alias,
 
@@ -217,7 +218,9 @@ extern stmt *stmt_binop(backend *be, stm
 extern stmt *stmt_Nop(backend *be, stmt *ops, sql_subfunc *op);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to