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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list