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