Changeset: 3fd382ea80f4 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3fd382ea80f4
Modified Files:
monetdb5/modules/mal/array.mx
sql/scripts/29_array.sql
sql/server/rel_select.c
Branch: sciql
Log Message:
Step 1/2 of fixing array slicing (with explicit step size)
Translate such array slicing into the new relation plan:
rel_project(
rel_select(rel, array_slice()),
dim1[, dim2, dim3])
diffs (truncated from 400 to 300 lines):
diff --git a/monetdb5/modules/mal/array.mx b/monetdb5/modules/mal/array.mx
--- a/monetdb5/modules/mal/array.mx
+++ b/monetdb5/modules/mal/array.mx
@@ -74,6 +74,10 @@ function filler_(cnt:lng, v:any_1)(id:ba
return (b4,b2);
end filler_;
+pattern slice(dim_strt:lng, dim_step:lng, dim_stop:lng, slc_strt:lng,
slc_step:lng, slc_stop:lng...):bat[:oid,:oid]
+address ARRAYslice
+comment "Compute the OIDs of all cells selected by an array slicing"
+
@= tilesAggrDecl
module array;
@@ -162,6 +166,8 @@ comment "Construct the count over all ti
array_export str ARRAYfiller_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr p);
array_export str ARRAYfiller(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr p);
+array_export str ARRAYslice(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr p);
+
@= array_defs
array_export str ARRAYseries_@1(int *ret, @1 *start, @1 *step, @1 *stop, int
*grp, int *series);
array_export str ARRAYtilesSum_@1(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
@@ -292,6 +298,17 @@ ARRAYfiller_bat(Client cntxt, MalBlkPtr
}
str
+ARRAYslice(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+ (void) cntxt;
+ (void) mb;
+ (void) stk;
+ (void) pci;
+
+ return MAL_SUCCEED;
+}
+
+str
ARRAYfiller(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
BAT *bn;
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,3 +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;
+
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
@@ -616,160 +616,202 @@ rel_arrayslice(mvc *sql, sql_table *t, c
dnode *idx_exp = NULL, *idx_term = NULL;
/* initial a new rel_select with selection expressions to be added
later*/
sql_rel *rel = rel_select(sql->sa, rel_basetable(sql, t, tname), NULL);
- sql_exp *ro = NULL, *ro2 = NULL, *slc_val = NULL, *exp = NULL, *ce =
NULL;
+ sql_exp *ce = NULL;
sql_column *col = NULL;
sql_subfunc *sf = NULL;
exp_kind ek = {type_value, card_value, FALSE};
+ int realSlice = 0;
assert(dimref->token == SQL_ARRAY_DIM_SLICE);
if (!t->valence)
- return sql_error(sql, 02, "array slicing over a table ('%s')not
allowed", t->base.name);
-
- /* Handling array slicing using normal SQL: WHERE <pred_exp> IN '('
<value_commalist> ')'.
- * Loop over all table columns and sliced columns. Translate each
slicing
- * <start>:<step>:<stop> into:
- * <column name> in '(' array_series(start, step, stop, 1, 1) ')'
- */
- for (cn = t->columns.set->h, idx_exp =
dimref->data.lval->h->next->data.lval->h;
- cn && idx_exp; cn = cn->next, idx_exp = idx_exp->next) {
- list *args = new_exp_list(sql->sa),
- *srng_exps = new_exp_list(sql->sa);
- sql_exp *col_strt = NULL, *col_step = NULL, *col_stop = NULL;
- int skip = 1;
-
- if (args == NULL || srng_exps == NULL)
+ return sql_error(sql, 02, "array slicing over a table
('%s.%s')not allowed", t->s->base.name, t->base.name);
+ if (dlist_length(dimref->data.lval->h->next->data.lval) > t->valence)
+ return sql_error(sql, 02, "array slicing over too many
dimensions");
+
+ /* For comparing the performance of array.slice and range selection */
+ for (idx_exp = dimref->data.lval->h->next->data.lval->h; idx_exp;
idx_exp = idx_exp->next) {
+ if (dlist_length(idx_exp->data.lval) == 3)
+ realSlice = 1;
+ }
+ if (realSlice && t->valence > 3)
+ return sql_error(sql, 02, "array slicing with step size over
arrays with more than three dimensions not supported yet");
+
+ /* If none of the slicing ranges has a step size, translate the slicing
into [range|point] selections */
+ if (!realSlice) {
+ sql_exp *ro = NULL, *ro2 = NULL, *exp = NULL;
+ for (cn = t->columns.set->h, idx_exp =
dimref->data.lval->h->next->data.lval->h;
+ cn && idx_exp; cn = cn->next, idx_exp =
idx_exp->next) {
+ list *srng_exps = new_exp_list(sql->sa);
+ sql_exp *dim_strt = NULL, *dim_step = NULL, *dim_stop =
NULL;
+ int skip = 1;
+
+ if (srng_exps == NULL)
+ return sql_error(sql, 02, "ARRAY SLICE: failed
to allocate space");
+
+ col = (sql_column *) cn->data;
+ while(!col->dim) { /* skip the non-dimensional
attributes in the table columns */
+ cn = cn->next;
+ col = (sql_column*)cn->data;
+ }
+
+ /* In case of '[*]', '[*:*]' or '[*:*:*]', don't slice
this column */
+ for (idx_term = idx_exp->data.lval->h; idx_term;
idx_term = idx_term->next)
+ if (idx_term->data.sym) skip = 0;
+ if (skip) continue;
+
+ if (col->dim->strt == lng_nil || col->dim->step ==
lng_nil || col->dim->stop == lng_nil)
+ return sql_error(sql, 02, "TODO: slicing over
unbounded dimension");
+
+ dim_strt = rel_check_type(sql, &col->type,
exp_atom_lng(sql->sa, col->dim->strt), type_cast);
+ dim_step = rel_check_type(sql, &col->type,
exp_atom_lng(sql->sa, col->dim->step), type_cast);
+ dim_stop = rel_check_type(sql, &col->type,
exp_atom_lng(sql->sa, col->dim->stop), type_cast);
+
+ /* Translate a slice expression into:
+ * a equal comparison, if the slicing expression is
'[' range_term ']'; or
+ * a range selection, if the slicing expression is
'[' range_term ':' range_term ']'; or
+ * a join between the sliced column and the list of
to be sliced dimensional values in slc_val,
+ * if the slicing expression is
'[' range_term ':' range_term ':' range_term ']'.
+ */
+ /* If the value of start/step/stop is omitted, we get
its value from the dimension definition. */
+ idx_term = idx_exp->data.lval->h;
+ if (dlist_length(idx_exp->data.lval) == 1) {
+ ro = rel_check_type(sql, &col->type,
rel_value_exp(sql, &rel, idx_term->data.sym, sql_where, ek), type_cast);
+ append(srng_exps, ro); /* sliced start */
+ append(srng_exps, dim_step); /* sliced step ==
original step */
+ append(srng_exps, exp_binop( /* sliced stop =
sliced start + original step */
+ sql->sa,
exp_copy(sql->sa, ro), exp_copy(sql->sa, dim_step),
+ sql_bind_func(sql->sa,
sql->session->schema, "sql_add", &col->type, &col->type, F_FUNC)));
+
+ if (!(ce = _slicing2basetable(sql, rel, tname,
col->base.name, srng_exps)))
+ return NULL;
+ exp = exp_column(sql->sa, tname,
col->base.name, &col->type, CARD_MULTI, 0, 0, ce->f);
+
+ /* [<ro>]: <(column) exp> '=' <ro> */
+ rel = rel_compare_exp_(sql, rel, exp, ro, NULL,
cmp_equal, 0);
+ if (rel == NULL)
+ return NULL;
+ } else { /* dlist_length(idx_exp->data.lval) == 2 */
+ /* sliced start */
+ ro = idx_term->data.sym ? /* check for '*' */
+ rel_check_type(sql, &col->type,
rel_value_exp(sql, &rel, idx_term->data.sym, sql_where, ek), type_cast) :
+ dim_strt;
+ append(srng_exps, ro);
+
+ /* sliced step == original step */
+ append(srng_exps, dim_step);
+
+ /* sliced stop */
+ idx_term = idx_term->next;
+ ro2 = idx_term->data.sym ?
+ rel_check_type(sql, &col->type,
rel_value_exp(sql, &rel, idx_term->data.sym, sql_where, ek), type_cast) :
+ dim_stop;
+ append(srng_exps, ro2);
+
+ if (!(ce = _slicing2basetable(sql, rel, tname,
col->base.name, srng_exps)))
+ return NULL;
+ exp = exp_column(sql->sa, tname,
col->base.name, &col->type, CARD_MULTI, 0, 0, ce->f);
+
+ if (col->dim->step > 0) {
+ /* [<ro>:<ro2>]: <ro> '<=' <(column)
exp> '<' <ro2> */
+ rel = rel_compare_exp_(sql, rel, exp,
ro, NULL, cmp_gte, 0);
+ if (rel == NULL)
+ return NULL;
+ rel = rel_compare_exp_(sql, rel, exp,
ro2, NULL, cmp_lt, 0);
+ if (rel == NULL)
+ return NULL;
+ } else { /* col->dim->step < 0 */
+ /* [<ro>:<ro2>]: <ro> '>=' <(column)
exp> '>' <ro2> */
+ rel = rel_compare_exp_(sql, rel, exp,
ro, NULL, cmp_lte, 0);
+ if (rel == NULL)
+ return NULL;
+ rel = rel_compare_exp_(sql, rel, exp,
ro2, NULL, cmp_gt, 0);
+ if (rel == NULL)
+ return NULL;
+ }
+ }
+ }
+ } else {
+ list *slc_args = new_exp_list(sql->sa), *dims =
new_exp_list(sql->sa);
+ sql_subtype *lng_tpe = sql_bind_localtype("lng");
+
+ if (slc_args == NULL || dims == NULL)
return sql_error(sql, 02, "ARRAY SLICE: failed to
allocate space");
- col = (sql_column *) cn->data;
- while(!col->dim) { /* skip the non-dimensional attributes in
the table columns */
- cn = cn->next;
- col = (sql_column*)cn->data;
- }
-
- /* In case of '[*]', '[*:*]' or '[*:*:*]', don't slice this
column */
- for (idx_term = idx_exp->data.lval->h; idx_term; idx_term =
idx_term->next)
- if (idx_term->data.sym) skip = 0;
- if (skip) continue;
-
- if (col->dim->strt == lng_nil || col->dim->step == lng_nil ||
col->dim->stop == lng_nil)
- return sql_error(sql, 02, "TODO: slicing over unbounded
dimension");
-
- col_strt = rel_check_type(sql, &col->type,
exp_atom_lng(sql->sa, col->dim->strt), type_cast);
- col_step = rel_check_type(sql, &col->type,
exp_atom_lng(sql->sa, col->dim->step), type_cast);
- col_stop = rel_check_type(sql, &col->type,
exp_atom_lng(sql->sa, col->dim->stop), type_cast);
-
- /* Translate a slice expression into:
- * a equal comparison, if the slicing expression is '['
range_term ']'; or
- * a range selection, if the slicing expression is '['
range_term ':' range_term ']'; or
- * a join between the sliced column and the list of to be
sliced dimensional values in slc_val,
- * if the slicing expression is '['
range_term ':' range_term ':' range_term ']'.
- */
- /* If the value of start/step/stop is omitted, we get its value
from the dimension definition. */
- idx_term = idx_exp->data.lval->h;
- if (idx_exp->data.lval->cnt == 1) {
- ro = rel_check_type(sql, &col->type, rel_value_exp(sql,
&rel, idx_term->data.sym, sql_where, ek), type_cast);
- append(srng_exps, ro); /* sliced start */
- append(srng_exps, col_step); /* sliced step == original
step */
- append(srng_exps, exp_binop( /* sliced stop = sliced
start + original step */
- sql->sa, exp_copy(sql->sa, ro),
exp_copy(sql->sa, col_step),
- sql_bind_func(sql->sa,
sql->session->schema, "sql_add", &col->type, &col->type, F_FUNC)));
-
+ for (cn = t->columns.set->h, idx_exp =
dimref->data.lval->h->next->data.lval->h;
+ cn && idx_exp; cn = cn->next, idx_exp =
idx_exp->next) {
+ list *srng_exps = new_exp_list(sql->sa);
+ sql_exp *dim_strt = NULL, *dim_step = NULL, *dim_stop =
NULL,
+ *slc_strt = NULL, *slc_step = NULL,
*slc_stop = NULL;
+
+ if (srng_exps == NULL)
+ return sql_error(sql, 02, "ARRAY SLICE: failed
to allocate space");
+
+ col = (sql_column *) cn->data;
+ while(!col->dim) { /* skip the non-dimensional
attributes in the table columns */
+ cn = cn->next;
+ col = (sql_column*)cn->data;
+ }
+
+ if (col->dim->strt == lng_nil || col->dim->step ==
lng_nil || col->dim->stop == lng_nil)
+ return sql_error(sql, 02, "TODO: slicing over
unbounded dimension");
+
+ /* If the value of start/step/stop is omitted, we get
its value from the dimension definition. */
+ dim_strt = exp_atom_lng(sql->sa, col->dim->strt);
+ dim_step = exp_atom_lng(sql->sa, col->dim->step);
+ dim_stop = exp_atom_lng(sql->sa, col->dim->stop);
+
+ /* The first idx_term is alreays the start */
+ idx_term = idx_exp->data.lval->h;
+ slc_strt = (idx_term->data.sym != NULL)?
+ /* [<idx_term>], [<idx_term>:???],
[<idx_term>:???:???] */
+ rel_check_type(sql, lng_tpe, rel_value_exp(sql,
&rel, idx_term->data.sym, sql_where, ek), type_cast):
+ /* ['*'], ['*':???], ['*':???:???] */
+ exp_copy(sql->sa, dim_strt); /* sliced start ==
original start */
+
+ /* a slicing step is given explicitly, IFF there are
three idx_terms and the second is not NULL */
+ idx_term = idx_term->next;
+ slc_step = (dlist_length(idx_exp->data.lval) == 3 &&
idx_term->data.sym != NULL)?
+ /* [???:<idx_term>:???] */
+ rel_check_type(sql, lng_tpe, rel_value_exp(sql,
&rel, idx_term->data.sym, sql_where, ek), type_cast):
+ /* [???], [???:???], [???:'*':???] */
+ exp_copy(sql->sa, dim_step); /* sliced step ==
original step */
+
+ /* the last idx_term, if exists, is always the slicing
stop */
+ idx_term = (dlist_length(idx_exp->data.lval) == 3)?
idx_term->next : idx_term;
+ slc_stop = (idx_term != NULL && idx_term->data.sym !=
NULL)?
+ /* [???:<idx_term>],[???:???:<idx_term>] */
+ rel_check_type(sql, lng_tpe, rel_value_exp(sql,
&rel, idx_term->data.sym, sql_where, ek), type_cast):
+ (idx_term == NULL &&
idx_exp->data.lval->h->data.sym != NULL)?
+ /* [<idx_term>] */
+ exp_binop( /* sliced stop = sliced
start + original step */
+ sql->sa,
exp_copy(sql->sa, slc_strt), exp_copy(sql->sa, dim_step),
+ sql_bind_func(sql->sa,
sql->session->schema, "sql_add", lng_tpe, lng_tpe, F_FUNC)):
+ /* ['*'], [???:'*'], [???:???:'*'] */
+ exp_copy(sql->sa, dim_stop); /* sliced
stop == original stop */
+
+ append(slc_args, dim_strt);
+ append(slc_args, dim_step);
+ append(slc_args, dim_stop);
+ append(slc_args, slc_strt);
+ append(slc_args, slc_step);
+ append(slc_args, slc_stop);
+ append(srng_exps, exp_copy(sql->sa, slc_strt));
+ append(srng_exps, exp_copy(sql->sa, slc_step));
+ append(srng_exps, exp_copy(sql->sa, slc_stop));
if (!(ce = _slicing2basetable(sql, rel, tname,
col->base.name, srng_exps)))
return NULL;
- exp = exp_column(sql->sa, tname, col->base.name,
&col->type, CARD_MULTI, 0, 0, ce->f);
-
- /* [<ro>]: <(column) exp> '=' <ro> */
- rel = rel_compare_exp_(sql, rel, exp, ro, NULL,
cmp_equal, 0);
- if (rel == NULL)
- return NULL;
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list