Changeset: d3b399699f6b for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d3b399699f6b
Added Files:
sql/test/sciql/Tests/07_tiling_04.sql
sql/test/sciql/Tests/07_tiling_04.stable.err
sql/test/sciql/Tests/07_tiling_04.stable.out
sql/test/sciql/Tests/08_subquery_01.sql
sql/test/sciql/Tests/08_subquery_01.stable.err
sql/test/sciql/Tests/08_subquery_01.stable.out
Modified Files:
monetdb5/modules/mal/array.mx
sql/server/rel_select.c
sql/test/sciql/Tests/00_syntax_error_01.stable.err
sql/test/sciql/Tests/00_syntax_error_02.stable.err
sql/test/sciql/Tests/00_syntax_error_03.stable.err
sql/test/sciql/Tests/00_syntax_error_04.stable.err
sql/test/sciql/Tests/00_syntax_error_05.stable.err
sql/test/sciql/Tests/All
Branch: sciql
Log Message:
Fixes in array tiling group by code
rel_select.c
- Sovled the problem of "no such array" in SciQL group by over an array
returned by a subquery by adding function that find the base name of a relation
give the alias
- implemented the SciQL group by case '[*]'
array.mx:
- remove implementation of OID, since it's not an SQL datatype
- a rather stupid error in computing the total cnt.
- check input values and better error msg in array.series
Added + approved two test queries for the fixes above
diffs (truncated from 1724 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
@@ -49,7 +49,6 @@ end series_;
@mal
module array;
-@:array_mdefs(oid)@
@:array_mdefs(bte)@
@:array_mdefs(sht)@
@:array_mdefs(int)@
@@ -58,6 +57,7 @@ module array;
@:array_mdefs(dbl)@
@-
to be dealt with differently
+@:array_mdefs(oid)@
@:array_mdefs(date)@
@:array_mdefs(daytime)@
@:array_mdefs(timestamp)@
@@ -206,7 +206,6 @@ array_export str ARRAYseries_@1(int *ret
array_export str ARRAYtilesSum_@1(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
array_export str ARRAYtilesAvg_@1(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
@h
-@:array_defs(oid)@
@:array_defs(bte)@
@:array_defs(sht)@
@:array_defs(int)@
@@ -215,6 +214,7 @@ array_export str ARRAYtilesAvg_@1(Client
@:array_defs(dbl)@
@-
to be dealt with differently
+@:array_defs(oid)@
@:array_defs(date)@
@:array_defs(daytime)@
@:array_defs(timestamp)@
@@ -245,13 +245,15 @@ ARRAYseries_@1(int *ret, @1 *start, @1 *
BUN cnt= 0;
int s,g;
- if ( *start < *stop && *step > 0) {
+ if ( *group < 1 )
+ throw(MAL, "array.series", "#groups must be > 0, got (%d)",
*group);
+ if ( *series < 1 )
+ throw(MAL, "array.series", "#series must be > 0, got (%d)",
*series);
+
+ if ( (*start < *stop && *step > 0) || (*start > *stop && *step < 0) ) {
cnt = (BUN) ceil(((*stop * 1.0 - *start) / *step)) * *group *
*series ;
} else
- if ( abs(*start) < abs(*stop) && abs(*step) > 0) {
- cnt = (BUN) ceil(((*stop * 1.0 + *start) / *step)) * *group *
*series ;
- } else
- throw(MAL, "array.series", "illegal range");
+ throw(MAL, "array.series", "Illegal dimension range,
[start:step:stop] have values: [@2:@2:@2]", *start, *step, *stop);
bn = BATnew(TYPE_void, TYPE_@1, cnt);
if ( bn == NULL)
throw(MAL, "array.series", MAL_MALLOC_FAIL);
@@ -285,15 +287,15 @@ ARRAYseries_@1(int *ret, @1 *start, @1 *
}
@c
-@:dim_wrapper_impl(oid)@
-@:dim_wrapper_impl(bte)@
-@:dim_wrapper_impl(sht)@
-@:dim_wrapper_impl(int)@
-@:dim_wrapper_impl(lng)@
-@:dim_wrapper_impl(flt)@
-@:dim_wrapper_impl(dbl)@
+@:dim_wrapper_impl(bte,%d)@
+@:dim_wrapper_impl(sht,%d)@
+@:dim_wrapper_impl(int,%d)@
+@:dim_wrapper_impl(lng,%lld)@
+@:dim_wrapper_impl(flt,%f)@
+@:dim_wrapper_impl(dbl,%f)@
@-
to be dealt with differently
+@:dim_wrapper_impl(oid," OIDFMT ")@
@:dim_wrapper_impl(date)@
@:dim_wrapper_impl(daytime)@
@:dim_wrapper_impl(timestamp)@
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
@@ -1954,6 +1954,22 @@ get_dimension(mvc *sql, sql_table *a, ch
return sql_error(sql, 02, "SELECT: dimension '%s' not found in array
'%s'", dname, a->base.name);
}
+static sql_column *
+get_nth_dimension(sql_table *a, int nth)
+{
+ int i = 0;
+ node *cn = a->columns.set->h;
+
+ for (; cn; cn = cn->next) {
+ if(((sql_column *) cn->data)->dim) {
+ if (i == nth)
+ return cn->data;
+ i++;
+ }
+ }
+ return NULL;
+}
+
static int
check_tiling_dimension(mvc *sql, char *dimnm, symbol *dim_ref)
{
@@ -1977,6 +1993,96 @@ check_tiling_dimension(mvc *sql, char *d
return 1;
}
+static char *
+_get_base_name(sql_exp *exp, char *alias)
+{
+ char *bnm = NULL;
+ node *n = NULL;
+
+ if (!exp || !alias)
+ return NULL;
+
+ switch(exp->type) {
+ case e_func:
+ case e_aggr:
+ for (n = ((list*)exp->l)->h; n; n = n->next) {
+ bnm = _get_base_name(n->data, alias);
+ if (bnm)
+ return bnm;
+ }
+ return NULL;
+ case e_convert:
+ return _get_base_name(exp->l, alias);
+ case e_cmp:
+ if(!(bnm = _get_base_name(exp->l, alias)))
+ return _get_base_name(exp->r, alias);
+ return bnm;
+ case e_column:
+ if (exp->rname && strcmp(exp->rname, alias) == 0) {
+ return exp->l;
+ }
+ return NULL;
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+/* Given the alias of a table/array, find in all expressions contained in 'rel'
+ * the original name of the base table/array.
+ */
+static char *
+get_base_name(sql_rel *rel, char *alias)
+{
+ char *bnm = NULL;
+ node *n = rel->exps->h;
+
+ if (!rel || !alias)
+ return NULL;
+
+ for ( ; n; n = n->next) {
+ bnm = _get_base_name(n->data, alias);
+ if (bnm)
+ return bnm;
+ }
+
+ switch(rel->op) {
+ case op_select:
+ case op_topn:
+ case op_sample:
+ return get_base_name(rel->l, alias);
+ break;
+ case op_join:
+ case op_left:
+ case op_right:
+ case op_full:
+ case op_semi:
+ case op_anti:
+ case op_union:
+ case op_except:
+ case op_inter:
+ if(!(bnm = get_base_name(rel->l, alias)))
+ return get_base_name(rel->r, alias);
+ break;
+ case op_table:
+ case op_project:
+ case op_groupby:
+ if(!(bnm = get_base_name(rel->l, alias))) {
+ if (!rel->r || !((list*)rel->r)->h)
+ return NULL;
+ for (n = ((list*)rel->r)->h; n; n = n->next) {
+ bnm = _get_base_name(n->data, alias);
+ if (bnm)
+ return bnm;
+ }
+ }
+ break;
+ default:
+ return NULL;
+ }
+ return bnm;
+}
+
#define ARRAY_TILING_MAX_DIMS 3
static list *
@@ -1984,11 +2090,12 @@ rel_arraytiling(mvc *sql, sql_rel **rel,
{
list *exps = new_exp_list(sql->sa), *offsets = NULL;
dlist *qname = NULL, *idx_exps = NULL;
- char *sname = NULL, *aname = NULL, *opnm = NULL;
+ char *sname = NULL, *aname = NULL, *aalias = NULL, *opnm = NULL;
dnode *n = NULL;
symbol *sym_tsta = NULL, *sym_tsto = NULL, *opl = NULL, *opr = NULL;
sql_schema *s = NULL;
sql_table *a = NULL;
+ int nth = 0; /* the n-th tiled dimension, needed for the '[*]' case, in
which we don't have the dimension name */
assert(rel && *rel && tile_def->token == SQL_ARRAY_DIM_SLICE &&
tile_def->type == type_list && dlist_length(tile_def->data.lval) == 2);
@@ -1996,12 +2103,12 @@ rel_arraytiling(mvc *sql, sql_rel **rel,
switch(dlist_length(qname)) {
case 1:
assert(qname->h->type == type_string);
- aname = qname->h->data.sval;
+ aalias = qname->h->data.sval;
break;
case 2:
assert(qname->h->type == type_string && qname->h->next->type ==
type_string);
sname = qname->h->data.sval;
- aname = qname->h->next->data.sval;
+ aalias = qname->h->next->data.sval;
break;
case 3:
return sql_error(sql, 02, "SELECT: array names of level > 2 not
supported");
@@ -2013,8 +2120,11 @@ rel_arraytiling(mvc *sql, sql_rel **rel,
if (sname && !(s=mvc_bind_schema(sql,sname)))
return sql_error(sql, 02, "3F000!SELECT: no such schema '%s'",
sname);
if (!s) s = cur_schema(sql);
- if (!(a = mvc_bind_table(sql, s, aname)))
- return sql_error(sql, 02, "42S02!SELECT: no such array
'%s.%s'", s->base.name, aname);
+ if (!(a = mvc_bind_table(sql, s, aalias))) {
+ if (!(aname = get_base_name(*rel, aalias)) || !(a =
mvc_bind_table(sql, s, aname))) {
+ return sql_error(sql, 02, "42S02!SELECT: no such array
'%s.%s'", s->base.name, aalias);
+ }
+ }
if (a->ndims > ARRAY_TILING_MAX_DIMS)
return sql_error(sql, 02, "SELECT: TODO: array tiling over
arrays with >%d dimensions", ARRAY_TILING_MAX_DIMS);
@@ -2025,112 +2135,123 @@ rel_arraytiling(mvc *sql, sql_rel **rel,
return sql_error(sql, 02, "SELECT: #dimensions (%d) in array
tiling fewer than #dimensions (%d) in the array --- not supported (yet?)",
dlist_length(idx_exps), a->ndims);
if (dlist_length(idx_exps) > ARRAY_TILING_MAX_DIMS)
return sql_error(sql, 02, "SELECT: TODO: array tiling over >%d
dimensions", ARRAY_TILING_MAX_DIMS);
- for (n = idx_exps->h; n; n = n->next) {
+ for (n = idx_exps->h; n; n = n->next, nth++) {
sql_exp *exp = NULL, *exp_os_sta = NULL, *exp_os_ste = NULL,
*exp_os_sto = NULL;
sql_column *dim = NULL;
exp_kind ek = {type_value, card_value, FALSE};
offsets = new_exp_list(sql->sa);
assert(n->type == type_list);
- /* The first is always the start of the range, to handle the
first 'index_term':
- * 1) extract and bind the dimension, which also checks if the
- * dimension exists in the array 'aname';
- * 2) extract the start-offset expression from the 'index_term',
- * create an exp_atom with "0" if not specified (case
- * SQL_COLUMN), and append it to 'exp->f'.
- */
- sym_tsta = n->data.lval->h->data.sym;
- switch (sym_tsta->token) {
- case SQL_COLUMN: /* '<column>' */
- if (!(exp = get_tiling_dimension(sql, *rel,
aname, sym_tsta, f)))
- return NULL;
- if (!(dim = get_dimension(sql, a, exp->name)))
- return NULL;
- exp_os_sta = exp_atom(sql->sa,
atom_general(sql->sa, &dim->type, "0"));
- break;
- case SQL_BINOP: /* '<column> <BINOP> <exp>' or '<exp>
<BINOP> <column>' */
- /* sym_tsta->data.lval->h: a list of a single
string, operator name
- * sym_tsta->data.lval->h->next: the symbol of
the left operand
- * sym_tsta->data.lval->h->next->next: the
symbol of the right operand
- */
- opnm =
sym_tsta->data.lval->h->data.lval->h->data.sval;
- opl = sym_tsta->data.lval->h->next->data.sym;
- opr =
sym_tsta->data.lval->h->next->next->data.sym;
- /* the <exp> could also be a SQL_COLUMN, but
then opl->data.sym->data.lval->h->type == type_int */
- if (opl->token == SQL_COLUMN &&
opl->data.lval->h->type == type_string) { /* '<column> +/- <exp>' */
- if (!(exp = get_tiling_dimension(sql,
*rel, aname, opl, f)))
+ if (n->data.lval->h->data.sym) {
+ sym_tsta = n->data.lval->h->data.sym;
+ /* The first is always the start of the range, to
handle the first 'index_term':
+ * 1) extract and bind the dimension, which also checks
if the
+ * dimension exists in the array 'aname';
+ * 2) extract the start-offset expression from the
'index_term',
+ * create an exp_atom with "0" if not specified (case
+ * SQL_COLUMN), and append it to 'exp->f'.
+ */
+ switch (sym_tsta->token) {
+ case SQL_COLUMN: /* '<column>' */
+ if (!(exp = get_tiling_dimension(sql,
*rel, aalias, sym_tsta, f)))
return NULL;
if (!(dim = get_dimension(sql, a,
exp->name)))
return NULL;
- if (is_addition(opnm)) {
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list