Changeset: 2168721f39bf for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2168721f39bf
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_gencode.c
        sql/rel.txt
        sql/scripts/29_array.sql
        sql/server/rel_select.c
Branch: sciql
Log Message:

Changed the array_slice function into a (new type of) filter function.

The array_slice function is a general implementation of array slicing, which is
 now used when one slicing range contains an explicit step size.
The array_slice function is now implemented as a filter function, so that cheap
 leftfetchjoin can be used to filter out the selected cells, i.s.o. expensive
 joins in the old code.
However, the implementation is a bit hacky, because the array_slice filter has
 different properties than the normal filters, namely, it doesn't have a single
 value at the left/right sides for the comparison, but takes a list of
 dimension/slicing ranges to compute the values that should be filtered out.
The hacks are documented in the code.


diffs (161 lines):

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
@@ -640,8 +640,24 @@ exp_bin(mvc *sql, sql_exp *e, stmt *left
                                 return j;
                         }
                        ops = sa_list(sql->sa);
-                       append(ops, r);
-                       append(ops, r2);
+                       if (list_length(e->r) > 2) {
+                               /* NB: this is a HACK to make the array_slice 
filter work.
+                                * Unlike the normal filters, the array_slice 
doesn't have
+                                *  right-side comparison value.
+                                * Instead, it has a list of dimension and 
slicing ranges,
+                                *  contained in e->r, that need to be passed 
to the filter
+                                *  function.
+                                * Here we create a stmt for each of them and 
add it to the ops
+                                *  list.
+                                */
+                               node *n;
+                               for (n = ((list*)e->r)->h; n; n = n->next) {
+                                       append(ops, exp_bin(sql, n->data, NULL, 
NULL, NULL, NULL, NULL, NULL));
+                               }
+                       } else { /* the normal/original filter case */
+                               append(ops, r);
+                               append(ops, r2);
+                       }
                        r = stmt_list(sql->sa, ops);
                        s = stmt_genselect(sql->sa, l, r, e->f, sel);
                         if (s && is_anti(e))
diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -1126,23 +1126,37 @@ _dumpstmt(backend *sql, MalBlkPtr mb, st
                                if (get_cmp(s) == cmp_filter) {
                                        node *n;
                                        char *mod, *fimp;
+                                       int isArraySlice = 0;
 
                                        if (backend_create_func(sql, 
s->op4.funcval->func) < 0)
                                                return -1;
                                        mod  = 
sql_func_mod(s->op4.funcval->func);
                                        fimp = 
sql_func_imp(s->op4.funcval->func);
+                                       isArraySlice = (strcmp(mod, "array") == 
0 && strcmp(fimp, "slice") == 0);
 
                                        q = newStmt(mb, mod, 
convertOperator(fimp));
-                                       q = pushArgument(mb, q, l);
-                                       if (sub > 0)
-                                               q = pushArgument(mb, q, sub);
+                                       /* NB: this is a HACK to make the 
array_slice filter work.
+                                        * The array_slice function computes 
the selected OIDs only
+                                        *  based on its scalar parameters.
+                                        * It doens't need a left-side column 
'l', nor does it
+                                        *  use/reduce any previous results 
'sub'.
+                                        */
+                                       if (!isArraySlice) {
+                                               q = pushArgument(mb, q, l);
+                                               if (sub > 0)
+                                                       q = pushArgument(mb, q, 
sub);
+                                       }
 
                                        for (n = s->op2->op4.lval->h; n; n = 
n->next) {
                                                stmt *op = n->data;
 
                                                q = pushArgument(mb, q, op->nr);
                                        }
-                                       q = pushBit(mb, q, anti);
+                                       /* We don't have any 'anti' comparison 
in array slicing
+                                        *  (yet). */
+                                       if (!isArraySlice) {
+                                               q = pushBit(mb, q, anti);
+                                       }
                                        s->nr = getDestVar(q);
                                        break;
                                }
diff --git a/sql/rel.txt b/sql/rel.txt
--- a/sql/rel.txt
+++ b/sql/rel.txt
@@ -99,8 +99,11 @@ e_convert
        -> r    list of from and to subtypes
 
 e_cmp
-       -> l    left sub expression
-       -> r    right sub expression (f second arg for range expressions)
+       -> l    left sub expression, or 
+                       the to be filtered dimension in case of an array slcing
+       -> r    right sub expression (f second arg for range expressions), or
+                       the (>= 6) parameters to the array_slice filter 
function in case of an array slicing
+       -> f    the compare/filter function
        -> flag compare type            
                (       cmp_gt = 0,
                        cmp_gte = 1,
diff --git a/sql/scripts/29_array.sql b/sql/scripts/29_array.sql
--- a/sql/scripts/29_array.sql
+++ b/sql/scripts/29_array.sql
@@ -155,7 +155,7 @@ create function array_count(val bigint, 
 create function array_count(val real,     dim1 int, offsets1 int, size1 int, 
dim2 int, offsets2 int, size2 int, dim3 int, offsets3 int, size3 int) returns 
bigint external name "array".cnt;
 create function array_count(val double,   dim1 int, offsets1 int, size1 int, 
dim2 int, offsets2 int, size2 int, dim3 int, offsets3 int, size3 int) returns 
bigint external name "array".cnt;
 
-create function array_slice(dim1_strt bigint, dim1_step bigint, dim1_stop 
bigint, slice1_strt bigint, slice1_step bigint, slice1_stop bigint) returns oid 
external name "array".slice;
-create function array_slice(dim1_strt bigint, dim1_step bigint, dim1_stop 
bigint, slice1_strt bigint, slice1_step bigint, slice1_stop bigint, dim2_strt 
bigint, dim2_step bigint, dim2_stop bigint, slice2_strt bigint, slice2_step 
bigint, slice2_stop bigint) returns oid external name "array".slice;
-create function array_slice(dim1_strt bigint, dim1_step bigint, dim1_stop 
bigint, slice1_strt bigint, slice1_step bigint, slice1_stop bigint, dim2_strt 
bigint, dim2_step bigint, dim2_stop bigint, slice2_strt bigint, slice2_step 
bigint, slice2_stop bigint, dim3_strt bigint, dim3_step bigint, dim3_stop 
bigint, slice3_strt bigint, slice3_step bigint, slice3_stop bigint) returns oid 
external name "array".slice;
+create filter function array_slice(dim1_strt bigint, dim1_step bigint, 
dim1_stop bigint, slice1_strt bigint, slice1_step bigint, slice1_stop bigint) 
external name "array".slice;
+create filter function array_slice(dim1_strt bigint, dim1_step bigint, 
dim1_stop bigint, slice1_strt bigint, slice1_step bigint, slice1_stop bigint, 
dim2_strt bigint, dim2_step bigint, dim2_stop bigint, slice2_strt bigint, 
slice2_step bigint, slice2_stop bigint) external name "array".slice;
+create filter function array_slice(dim1_strt bigint, dim1_step bigint, 
dim1_stop bigint, slice1_strt bigint, slice1_step bigint, slice1_stop bigint, 
dim2_strt bigint, dim2_step bigint, dim2_stop bigint, slice2_strt bigint, 
slice2_step bigint, slice2_stop bigint, dim3_strt bigint, dim3_step bigint, 
dim3_stop bigint, slice3_strt bigint, slice3_step bigint, slice3_stop bigint) 
external name "array".slice;
 
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -732,10 +732,10 @@ rel_arrayslice(mvc *sql, sql_table *t, c
                        }
                }
        } else {
-               list *slc_args = new_exp_list(sql->sa), *dims = 
new_exp_list(sql->sa);
+               list *slc_args = new_exp_list(sql->sa), *cols = 
new_exp_list(sql->sa);
                sql_subtype *lng_tpe = sql_bind_localtype("lng");
 
-               if (slc_args == NULL || dims == NULL)
+               if (slc_args == NULL || cols == NULL)
                        return sql_error(sql, 02, "ARRAY SLICE: failed to 
allocate space");
 
                for (cn = t->columns.set->h, idx_exp = 
dimref->data.lval->h->next->data.lval->h;
@@ -749,6 +749,8 @@ rel_arrayslice(mvc *sql, sql_table *t, c
 
                        col = (sql_column *) cn->data;
                        while(!col->dim) { /* skip the non-dimensional 
attributes in the table columns */
+                               append(cols, exp_column(sql->sa, tname, 
col->base.name, &col->type, CARD_MULTI, 0, 0, NULL));
+
                                cn = cn->next;
                                col = (sql_column*)cn->data;
                        }
@@ -801,16 +803,21 @@ rel_arrayslice(mvc *sql, sql_table *t, c
                        append(srng_exps, exp_copy(sql->sa, slc_stop));
                        if (!(ce = _slicing2basetable(sql, rel, tname, 
col->base.name, srng_exps)))
                                return NULL;
-                       append(dims, exp_column(sql->sa, tname, col->base.name, 
&col->type, CARD_MULTI, 0, 0, ce->f));
-               }
-
-               sf = sql_bind_func_(sql->sa, mvc_bind_schema(sql, "sys"), 
"array_slice", exps_subtype(slc_args), F_FUNC);
+                       append(cols, exp_column(sql->sa, tname, col->base.name, 
&col->type, CARD_MULTI, 0, 0, ce->f));
+               }
+
+               sf = sql_bind_func_(sql->sa, mvc_bind_schema(sql, "sys"), 
"array_slice", exps_subtype(slc_args), F_FILT);
                if (!sf)
                        return sql_error(sql, 02, "failed to bind to the SQL 
function \"array_slice\"");
-               /* add the array.slicing op to the rel_select to select the 
slicing candidates */
-               rel_select_add_exp(rel, exp_op(sql->sa, slc_args, sf));
-               /* then project the selection on all dimensions */
-               rel = rel_project(sql->sa, rel, dims);
+
+               /* apply our array_slice filter function on all columns of the 
sliced array */
+               for (cn = cols->h; cn; cn = cn->next) {
+                       /* give the to be sliced column cn->data as the left 
side exp of
+                        * the filter exp, the function args slc_args as the 
right side exp
+                        * of the filter exp */
+                       ce = exp_filter(sql->sa, cn->data, slc_args, sf, 0);
+                       rel = rel_push_select(sql->sa, rel, cn->data, ce);
+               }
        }
        return rel;
 }
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to