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