Changeset: c0c009267fd8 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c0c009267fd8
Modified Files:
        sql/server/rel_select.c
Branch: sciql
Log Message:

many fixes and some extensions to yesterday's Part 1 of array tiling for TELEIOS

- create sql_exp for the array tiling offsets, i.s.o., extracting the ATOMs
- implemented several TODOs


diffs (truncated from 435 to 300 lines):

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
@@ -34,6 +34,9 @@
 #define rel_groupby_gbe(sa,r,e) rel_groupby(sa, r, append(new_exp_list(sa), e))
 #define ERR_AMBIGUOUS          050000
 
+#define is_addition(fname) (strcmp(fname, "sql_add") == 0)
+#define is_substraction(fname) (strcmp(fname, "sql_sub") == 0)
+
 sql_rel *
 rel_dup(sql_rel *r)
 {
@@ -1818,6 +1821,25 @@ get_tiling_dimension(mvc *sql, sql_rel *
        return exp;
 }
 
+static sql_column *
+get_dimension(mvc *sql, sql_table *a, char *dname)
+{
+       node *cn = NULL;
+       sql_column *col = NULL;
+
+       for (cn = a->columns.set->h; cn; cn = cn->next) {
+               col = (sql_column *) cn->data;
+               if (strcmp(col->base.name, dname) == 0) {
+                       if (!col->dim)
+                               return sql_error(sql, 02, "SELECT: array tiling 
over non-dimensional column '%s'", dname);
+                       if (col->type.type->localtype != TYPE_bte && 
col->type.type->localtype != TYPE_sht && col->type.type->localtype != TYPE_int 
&& col->type.type->localtype != TYPE_lng)
+                               return sql_error(sql, 02, "SELECT: array tiling 
over non-integer-typed dimension ('%s', type '%s') not supported", dname, 
col->type.type->sqlname);
+                       return col;
+               }
+       }
+       return sql_error(sql, 02, "SELECT: dimension '%s' not found in array 
'%s'", dname, a->base.name);
+}
+
 static int
 check_tiling_dimension(mvc *sql, char *dimnm, symbol *dim_ref)
 {
@@ -1845,41 +1867,70 @@ static list *
 rel_arraytiling(mvc *sql, sql_rel **rel, symbol *tile_def, int f)
 {
        list *exps = new_exp_list(sql->sa);
-       sql_exp *exp = NULL;
        dlist *qname = NULL, *idx_exps = NULL;
-       char *aname = NULL, *opnm = NULL;
+       char *sname = NULL, *aname = NULL, *opnm = NULL;
        dnode *n =  NULL;
        symbol *tstt = NULL, *tstp =  NULL, *opl = NULL, *opr = NULL;
+       sql_schema *s = NULL;
+       sql_table *a = NULL;
 
        assert(rel && *rel && tile_def->token == SQL_ARRAY_DIM_SLICE && 
tile_def->type == type_list && dlist_length(tile_def->data.lval) == 2);
-       /* TODO: 
-        * - check if the array has only integer typed dimensions
-        * - check if the array has more than 2 dimensions
-        */
        
        qname = tile_def->data.lval->h->data.lval;
-       if (dlist_length(qname) > 1)
-               return sql_error(sql, 02, "SELECT: array names of level > 1 in 
array tiling not supported");
-       assert(qname->h->type == type_string);
-       aname = qname->h->data.sval;
+       switch(dlist_length(qname)) {
+       case 1:
+               assert(qname->h->type == type_string);
+               aname = 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;
+               break;
+       case 3:
+               return sql_error(sql, 02, "SELECT: array names of level > 2 not 
supported");
+               break;
+       default: /* should never reach here */
+               return sql_error(sql, 02, "SELECT: invalid array reference in 
GROUP BY");
+       }
+       /* need the base array for the dimension info. */
+       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->ndims > 2)
+               return sql_error(sql, 02, "SELECT: TODO: array tiling over 
arrays with >2 dimensions");
 
        idx_exps = tile_def->data.lval->h->next->data.lval;
+       if (dlist_length(idx_exps) > a->ndims)
+               /* FIXME: why a->ndims == 0 ???!!! */
+               /* return sql_error(sql, 02, "SELECT: #dimensions (%d) in array 
tiling larger than #dimensions (%d) in the array", dlist_length(idx_exps), 
a->ndims); */
        if (dlist_length(idx_exps) > 2)
                return sql_error(sql, 02, "SELECT: TODO: array tiling over >2 
dimensions");
        for (n = idx_exps->h; n; n = n->next) {
+               sql_exp *exp = NULL, *offset_stt = NULL, *offset_stp = NULL;
+               sql_column *dim = NULL;
+               exp_kind ek = {type_value, card_value, FALSE};
+               list *offsets = new_exp_list(sql->sa);
+
                assert(n->type == type_list);
                tstt = n->data.lval->h->data.sym;
 
                switch (dlist_length(n->data.lval)) {
-               case 1:  /* [index_term] */
+               case 1:  /* <index_term> */
                        switch (tstt->token) {
                        case SQL_COLUMN: /* '<column>' */
                                if (!(exp = get_tiling_dimension(sql, *rel, 
aname, tstt, f)))
                                        return NULL;
-                               if(!(exp->f = GDKmalloc(sizeof(lng)*2)))
+                               if (!(dim = get_dimension(sql, a, exp->name)))
                                        return NULL;
-                               ((lng*)exp->f)[0] = 0;
-                               ((lng*)exp->f)[1] = 1;
+                               /* array tiling range start */
+                               append(offsets, exp_atom(sql->sa, 
atom_general(sql->sa, &dim->type, "0")));
+                               /* array tiling range stop, which, in case of a 
single <index_term>, is just '1' to make the range only include '0' */
+                               append(offsets, exp_atom(sql->sa, 
atom_general(sql->sa, &dim->type, "1")));
+                               /* use the free 'f' in e_column to pass the 
tiling ranges */
+                               exp->f = offsets;
                                break;
                        case SQL_BINOP: /* '<column> <BINOP> <exp>' or '<exp> 
<BINOP> <column>' */
                                /* tstt->data.lval->h: a list of a single 
string, operator name
@@ -1889,152 +1940,128 @@ rel_arraytiling(mvc *sql, sql_rel **rel,
                                opnm = 
tstt->data.lval->h->data.lval->h->data.sval;
                                opl = tstt->data.lval->h->next->data.sym;
                                opr = tstt->data.lval->h->next->next->data.sym;
-                               if (strcmp(opnm, "sql_add") != 0 && 
strcmp(opnm, "sql_sub") != 0)
-                                       return sql_error(sql, 02, "SELECT: 
binary expressions other than '+' and '-' in array tiling offset not supported 
yet");
-
-                               if (opl->token == SQL_COLUMN) { /* '<column> 
+/- <exp>' */
+                               /* 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)))
                                                return NULL;
-
-                                       if (opr->token == SQL_ATOM) {
-                                               atom *a = ((AtomNode *)opl)->a;
-                                               lng lval = 0;
-
-                                               if (strcmp(opnm, "sql_sub") == 
0)
-                                                       atom_neg(a);
-                                               if(!(exp->f = 
GDKmalloc(sizeof(lng)*2)))
-                                                       return NULL;
-                                               lval = atom_get_int(a);
-                                               ((lng*)exp->f)[0] = lval;
-                                               /* FIXME: should be 'lval + 
dim->step'! */
-                                               ((lng*)exp->f)[1] = lval + 1;
+                                       if (!(dim = get_dimension(sql, a, 
exp->name)))
+                                               return NULL;
+                                       if (is_addition(opnm)) {
+                                               offset_stt = 
rel_check_type(sql, &dim->type, rel_value_exp(sql, rel, opr, sql_where, ek), 
type_cast);
+                                       } else if (is_substraction(opnm)){
+                                               offset_stt = exp_unop(sql->sa, 
rel_check_type(sql, &dim->type, rel_value_exp(sql, rel, opr, sql_where, ek), 
type_cast), sql_bind_func(sql->sa, sql->session->schema, "sql_neg", &dim->type, 
NULL, F_FUNC));
                                        } else {
-                                               return sql_error(sql, 02, 
"SELECT: complex expressions as array tiling offset not supported yet");
+                                               return sql_error(sql, 02, 
"SELECT: binary expressions other than '+' and '-' in array tiling offset not 
supported yet");
                                        }
-                               } else if (opr->token == SQL_COLUMN) { /* 
'<exp> +/- <column>' */
-                                       return sql_error(sql, 02, "SELECT: 
TODO: implement the '<exp> +/1 <column>' case!");
+                                       /* In case of a single <index_term> the 
offset_stp is just offset_stt + 1 to make the range only include offset_stt */
+                                       offset_stp = exp_binop(sql->sa, 
offset_stt, exp_atom(sql->sa, atom_general(sql->sa, &dim->type, "1")), 
sql_bind_func(sql->sa, sql->session->schema, "sql_add", &dim->type, &dim->type, 
F_FUNC));
+                                       append(offsets, offset_stt);
+                                       append(offsets, offset_stp);
+                                       /* use the free 'f' in e_column to pass 
the tiling ranges */
+                                       exp->f = offsets;
+                               } else if (opr->token == SQL_COLUMN && 
opr->data.lval->h->type == type_string) { /* '<exp> +/- <column>' */
+                                       return sql_error(sql, 02, "SELECT: 
TODO: implement the '<exp> +/- <column>' case in array tiling!");
+                               } else {
+                                       return sql_error(sql, 02, "SELECT: 
absolute array tiling offset not supported yet");
+                               }
+
+                               break;
+                       default: /* '<exp> '*/
+                               return sql_error(sql, 02, "SELECT: absolute 
array tiling offset not supported yet");
+                       }
+                       break;
+               case 2: /* <index_term> : <index_term> */
+                       switch (tstt->token) {
+                       /* 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'.
+                        */
+                       case SQL_COLUMN: /* '<column>' */
+                               if (!(exp = get_tiling_dimension(sql, *rel, 
aname, tstt, f)))
+                                       return NULL;
+                               if (!(dim = get_dimension(sql, a, exp->name)))
+                                       return NULL;
+                               /* array tiling range start */
+                               append(offsets, exp_atom(sql->sa, 
atom_general(sql->sa, &dim->type, "0")));
+                               break;
+                       case SQL_BINOP: /* '<column> <BINOP> <exp>' or '<exp> 
<BINOP> <column>' */
+                               opnm = 
tstt->data.lval->h->data.lval->h->data.sval;
+                               opl = tstt->data.lval->h->next->data.sym;
+                               opr = tstt->data.lval->h->next->next->data.sym;
+                               if (opl->token == SQL_COLUMN && 
opl->data.lval->h->type == type_string) { /* '<column> +/- <exp>' */
+                                       if (!(exp = get_tiling_dimension(sql, 
*rel, aname, opl, f)))
+                                               return NULL;
+                                       if (!(dim = get_dimension(sql, a, 
exp->name)))
+                                               return NULL;
+                                       if (is_addition(opnm)) {
+                                               offset_stt = 
rel_check_type(sql, &dim->type, rel_value_exp(sql, rel, opr, sql_where, ek), 
type_cast);
+                                               /* in case of a single 
<index_term> the stop-offset is just start-offset + 1 to ensure start-offset 
will be selected */
+                                       } else if (is_substraction(opnm)){
+                                               offset_stt = exp_unop(sql->sa, 
rel_check_type(sql, &dim->type, rel_value_exp(sql, rel, opr, sql_where, ek), 
type_cast), sql_bind_func(sql->sa, sql->session->schema, "sql_neg", &dim->type, 
NULL, F_FUNC));
+                                       } else {
+                                               return sql_error(sql, 02, 
"SELECT: binary expressions other than '+' and '-' in array tiling offset not 
supported yet");
+                                       }
+                                       append(offsets, offset_stt);
+                               } else if (opr->token == SQL_COLUMN && 
opr->data.lval->h->type == type_string) { /* '<exp> +/- <column>' */
+                                       return sql_error(sql, 02, "SELECT: 
TODO: implement the '<exp> +/- <column>' case!");
                                } else {
                                        return sql_error(sql, 02, "SELECT: 
absolute array tiling offset not supported yet");
                                }
                                break;
-                       default: /* '<exp>' or '<ATOM>' */
+                       default: /* '<exp>' */
                                return sql_error(sql, 02, "SELECT: absolute 
array tiling offset not supported yet");
                        }
-                       break;
-               case 2: /* [index_term : index_term] */
-                       /* For the first 'index_term', 1) extract and 2) bind 
the dimension
-                        * => 3) check if the dimension exists (in array 
'aname').
-                        * 4) (Mis)use the unused 'e_column->f' to store two 
lng numbers,
-                        *  denoting the start and stop ranges of the tiles, 
respectively.
-                        * TODO: replace this simple hack with list of rel_exp 
to be able
-                        *  to handle other data types and more complex 
expressions, or
-                        *  even find another alternative to pass the 
information.
-                        * 5) Extract the start offset from the 'index_term', 0 
if not
-                        *  specified, and 6) store it in 'e_column->f[0]'.
-                        */
-                       switch (tstt->token) {
-                       case SQL_COLUMN:
-                               if (!(exp = get_tiling_dimension(sql, *rel, 
aname, tstt, f)))
-                                       return NULL;
-                               if(!(exp->f = GDKmalloc(sizeof(lng)*2)))
-                                       return NULL;
-                               ((lng*)exp->f)[0] = 0;
-                               break;
-                       case SQL_BINOP:
-                               opnm = 
tstt->data.lval->h->data.lval->h->data.sval;
-                               opl = tstt->data.lval->h->next->data.sym;
-                               opr = tstt->data.lval->h->next->next->data.sym;
-                               if (strcmp(opnm, "sql_add") != 0 && 
strcmp(opnm, "sql_sub") != 0)
-                                       return sql_error(sql, 02, "SELECT: 
binary expressions other than '+' and '-' in array tiling offset not supported 
yet");
-                               if (opl->token == SQL_COLUMN) { /* '<column> 
+/- <exp>' */
-                                       if (!(exp = get_tiling_dimension(sql, 
*rel, aname, opl, f)))
-                                               return NULL;
-                                       if (opr->token == SQL_ATOM) {
-                                               atom *a = ((AtomNode *)opr)->a;
-                                               if (strcmp(opnm, "sql_sub") == 
0)
-                                                       atom_neg(a);
-                                               if(!(exp->f = 
GDKmalloc(sizeof(lng)*2)))
-                                                       return NULL;
-                                               ((lng*)exp->f)[0] = 
atom_get_int(a);
-                                       } else {
-                                               return sql_error(sql, 02, 
"SELECT: complex expressions as array tiling offset not supported yet");
-                                       }
-                               } else if (opr->token == SQL_COLUMN) { /* 
'<exp> +/- <column>' */
-                                       return sql_error(sql, 02, "SELECT: 
TODO: implement the '<exp> +/1 <column>' case!");
-                               } else {
-                                       return sql_error(sql, 02, "SELECT: 
absolute array tiling offset not supported yet");
-                               }
-                               break;
-                       default:
-                               return sql_error(sql, 02, "SELECT: absolute 
array tiling offset not supported yet");
-                       }
-
-                       /* For the second 'index_term', 1) extract the 
dimension =>
-                        *  2) check if the dimension name matches the 
dimension name in
-                        *  the first 'index_term'.
-                        * 3) Extract the stop offset from the 'index_term', 0 
if not
-                        *  specified, 4) check if it is larger than the start 
offset and
-                        *  5) store it in the 'e_column->f[1]'
-                        */
+
                        tstp = n->data.lval->h->next->data.sym;
                        switch (tstp->token) {
+                       /* To handle the second 'index_term':
+                        * 1) extract and _check_ if the dimension name matches 
the
+                        *    dimension name in the first 'index_term'.
+                        * 2) extract the stop-offset expression from the 
'index_term',
+                        *    create an exp_atom with "0" if not specified (case
+                        *    SQL_COLUMN), and append it to 'exp->f'.
+                        */
                        case SQL_COLUMN:
-                               if (!check_tiling_dimension(sql, exp->name, 
tstp)) {
-                                       GDKfree(exp->f);
+                               if (!check_tiling_dimension(sql, exp->name, 
tstp))
                                        return NULL;
-                               }
-                               if (((lng*)exp->f)[0] >= 0) {
-                                       lng val = ((lng*)exp->f)[0];
-                                       GDKfree(exp->f);
-                                       return sql_error(sql, 02, "SELECT: 
invalid array tiling range [%lld, 0)", val);
-                               }
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to