Changeset: 035e9c51b99f for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=035e9c51b99f
Modified Files:
sql/server/rel_schema.c
sql/server/rel_select.c
sql/server/sql_parser.y
Branch: sciql
Log Message:
merging
diffs (truncated from 609 to 300 lines):
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
@@ -33,6 +33,17 @@ create function array_series("start" big
create function array_series("start" float, step float, stop float, N integer,
M integer) returns table (id bigint, dimval float)
external name "array".series;
+create function array_series1("start" tinyint, step tinyint, stop tinyint, N
integer, M integer) returns table (idimval tinyint)
+ external name "array".series_;
+create function array_series1("start" smallint, step smallint, stop smallint,
N integer, M integer) returns table (dimval smallint)
+ external name "array".series_;
+create function array_series1("start" integer, step integer, stop integer, N
integer, M integer) returns table (dimval integer)
+ external name "array".series_;
+create function array_series1("start" bigint, step bigint, stop bigint, N
integer, M integer) returns table (dimval bigint)
+ external name "array".series_;
+create function array_series1("start" float, step float, stop float, N
integer, M integer) returns table (dimval float)
+ external name "array".series_;
+
create function array_filler(cnt bigint, val tinyint) returns table (id
bigint, cellval tinyint)
external name "array".filler;
create function array_filler(cnt bigint, val smallint) returns table (id
bigint, cellval smallint)
diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c
--- a/sql/server/rel_schema.c
+++ b/sql/server/rel_schema.c
@@ -1040,6 +1040,7 @@ rel_create_table(mvc *sql, sql_schema *s
list *args = new_exp_list(sql->sa), *col_exps =
new_exp_list(sql->sa);
sql_exp *e = NULL, *func_exp = NULL;
sql_subtype *oid_tpe = sql_bind_localtype("oid");
+ sql_subfunc *sf = NULL;
if (sc->dim){
/* TODO: can we avoid computing these
'atom_general' twice? */
@@ -1048,7 +1049,10 @@ rel_create_table(mvc *sql, sql_schema *s
append(args, exp_atom(sql->sa,
atom_general(sql->sa, &sc->type, sc->dim->stop)));
append(args, exp_atom_int(sql->sa, N[i]));
append(args, exp_atom_int(sql->sa, M[i]));
- func_exp = exp_op(sql->sa, args,
sql_bind_func_(sql->sa, sql->session->schema, "array_series",
exps_subtype(args), F_FUNC));
+ sf = sql_bind_func_(sql->sa,
sql->session->schema, "array_series", exps_subtype(args), F_FUNC);
+ if (!sf)
+ return sql_error(sql, 02, "failed to
bind to the SQL function \"array_series\"");
+ func_exp = exp_op(sql->sa, args, sf);
/* TODO: what are the correct values for card
and intern? */
if (!id_l) {
id_l = exp_column(sql->sa,
sc->base.name, "id", oid_tpe, CARD_MULTI, (!sc->dim && !sc->def)?1:0, 0);
@@ -1073,7 +1077,10 @@ rel_create_table(mvc *sql, sql_schema *s
}
append(args, exp_atom_lng(sql->sa, cntall));
append(args, e);
- func_exp = exp_op(sql->sa, args,
sql_bind_func_(sql->sa, sql->session->schema, "array_filler",
exps_subtype(args), F_FUNC));
+ sf = sql_bind_func_(sql->sa,
sql->session->schema, "array_filler", exps_subtype(args), F_FUNC);
+ if (!sf)
+ return sql_error(sql, 02, "failed to
bind to the SQL function \"array_filler\"");
+ func_exp = exp_op(sql->sa, args, sf);
if (!id_l) {
id_l = exp_column(sql->sa,
sc->base.name, "id", oid_tpe, CARD_MULTI, (!sc->dim && !sc->def)?1:0, 0);
append(col_exps, id_l);
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
@@ -431,6 +431,97 @@ rel_copy( sql_allocator *sa, sql_rel *i
return rel;
}
+static sql_rel *
+rel_arrayslice(mvc *sql, sql_table *t, char *tname, symbol *dimref)
+{
+ node *cn = NULL;
+ dnode *idx_exp = NULL, *idx_term = NULL;
+ sql_rel *rel_tbl = rel_basetable(sql, t, tname), *rel =
rel_basetable(sql, t, tname);
+ sql_exp *col_exp = NULL, *slc_val = NULL, *expin = NULL;
+ sql_column *col = NULL;
+ sql_subfunc *sf = NULL;
+ exp_kind ek = {type_value, card_value, FALSE};
+
+ assert(dimref->token == SQL_ARRAY_INDEX);
+
+ if (t->ndims)
+ 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);
+ int skip = 1;
+
+ 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;
+
+ /* build the slc_val expression, which is going to compute a
list of to be sliced dimensional values. */
+ idx_term = idx_exp->data.lval->h;
+ if(idx_exp->data.lval->cnt == 1) {
+ slc_val = rel_check_type(sql, &col->type,
rel_value_exp(sql, &rel, idx_term->data.sym, sql_where, ek), type_cast);
+ } else {
+ /* If the value of start/step/stop is omitted, we get
its value from the dimension definition.
+ * TODO: deal with unbounded dimension */
+ if (!col->dim->start || !col->dim->step ||
!col->dim->stop)
+ return sql_error(sql, 02, "slicing over
unbounded dimension not supported");
+
+ /* the first <exp> is always the start */
+ append(args, 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) :
+ exp_atom(sql->sa, atom_general(sql->sa,
&col->type, col->dim->start)));
+
+
+ if(idx_exp->data.lval->cnt == 2) {
+ append(args, exp_atom(sql->sa,
atom_general(sql->sa, &col->type, col->dim->step)));
+ } else {
+ idx_term = idx_term->next;
+ append(args, idx_term->data.sym ?
+ rel_check_type(sql, &col->type,
rel_value_exp(sql, &rel, idx_term->data.sym, sql_where, ek), type_cast) :
+ exp_atom(sql->sa, atom_general(sql->sa,
&col->type, col->dim->step)));
+ }
+
+ idx_term = idx_term->next;
+ append(args, idx_term->data.sym ?
+ rel_check_type(sql, &col->type,
rel_value_exp(sql, &rel, idx_term->data.sym, sql_where, ek), type_cast) :
+ exp_atom(sql->sa, atom_general(sql->sa,
&col->type, col->dim->stop)));
+
+ /* Only create 1 group and repeat the numbers once */
+ append(args, exp_atom_int(sql->sa, 1));
+ append(args, exp_atom_int(sql->sa, 1));
+ sf = sql_bind_func_(sql->sa, sql->session->schema,
"array_series1", exps_subtype(args), F_FUNC);
+ if (!sf)
+ return sql_error(sql, 02, "failed to bind to
the SQL function \"array_series\"");
+ slc_val = exp_op(sql->sa, args, sf);
+ }
+
+ /* <col_exp> IN '(' <slc_val> ')' */
+ col_exp = exp_column(sql->sa, t->base.name, col->base.name,
&col->type, CARD_MULTI, 0, 0);
+ exp_label(sql->sa, slc_val, ++sql->label);
+ expin = exp_in(sql->sa, col_exp, append(new_exp_list(sql->sa),
slc_val), cmp_in);
+ rel = rel_select(sql->sa, rel, expin);
+ }
+
+ /* the number of sliced dimensions must be smaller than or equal to the
number of dimensions */
+ if (idx_exp)
+ return sql_error(sql, 02, "array slicing over too many
columns");
+
+ rel->card = rel->card > exps_card(rel_tbl->exps) ? rel->card :
exps_card(rel_tbl->exps);
+ return rel_project(sql->sa, rel, rel_tbl->exps);
+}
+
sql_rel *
_rel_basetable(sql_allocator *sa, sql_table *t, char *atname)
{
@@ -1538,11 +1629,11 @@ table_ref(mvc *sql, sql_rel *rel, symbol
sql_table *t = NULL;
(void)rel;
- if (tableref->token == SQL_NAME) {
+ if (tableref->token == SQL_NAME || tableref->token == SQL_ARRAY) {
sql_rel *temp_table = NULL;
- char *sname = qname_schema(tableref->data.lval->h->data.lval);
+ char *sname = tableref->token == SQL_NAME ?
qname_schema(tableref->data.lval->h->data.lval) :
qname_schema(tableref->data.lval->h->data.sym->data.lval->h->data.lval);
sql_schema *s = NULL;
- tname = qname_table(tableref->data.lval->h->data.lval);
+ tname = tableref->token == SQL_NAME ?
qname_table(tableref->data.lval->h->data.lval) :
qname_table(tableref->data.lval->h->data.sym->data.lval->h->data.lval);
if (sname && !(s=mvc_bind_schema(sql,sname)))
return sql_error(sql, 02, "SELECT: no such schema
'%s'", sname);
@@ -1569,13 +1660,14 @@ table_ref(mvc *sql, sql_rel *rel, symbol
}
}
if (!t && !temp_table) {
- return sql_error(sql, 02, "SELECT: no such table '%s'",
tname);
+ return sql_error(sql, 02, "SELECT: no such %s '%s'",
tableref->token==SQL_ARRAY?"array":"table", tname);
} else if (!temp_table && !table_privs(sql, t, PRIV_SELECT)) {
return sql_error(sql, 02, "SELECT: access denied for %s
to table '%s.%s'", stack_get_string(sql, "current_user"), s->base.name, tname);
}
if (tableref->data.lval->h->next->data.sym) { /* AS */
tname =
tableref->data.lval->h->next->data.sym->data.lval->h->data.sval;
}
+
if (temp_table && !t) {
node *n;
list *exps = rel_projections(sql, temp_table, NULL, 1,
1);
@@ -1610,7 +1702,7 @@ table_ref(mvc *sql, sql_rel *rel, symbol
}
return rel;
}
- return rel_basetable(sql, t, tname);
+ return tableref->token == SQL_ARRAY ? rel_arrayslice(sql, t,
tname, tableref->data.lval->h->data.sym) : rel_basetable(sql, t, tname);
} else if (tableref->token == SQL_VALUES) {
return rel_values(sql, tableref);
} else if (tableref->token == SQL_TABLE) {
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -267,6 +267,7 @@ int yydebug=1;
dimension
array_dim_ref
array_cell_ref
+ index_term
%type <type>
data_type
@@ -389,7 +390,6 @@ int yydebug=1;
dim_exp
index_exp /* position indices of array cells */
index_exp_list
- index_term
array_element_def_list
@@ -1683,7 +1683,7 @@ dim_range_list:
}
;
-dim_range :
+dim_range:
'[' dim_exp ':' dim_exp ':' dim_exp ']'
{
dlist *l = L();
@@ -1707,7 +1707,7 @@ dim_range :
}
;
-dim_exp :
+dim_exp:
literal
{
$$= append_symbol(L(), $1);
@@ -1722,6 +1722,7 @@ dim_exp :
{
$$= append_symbol(L(), NULL);
}
+ ;
serial_opt_params:
/* empty: return the defaults */
@@ -3195,12 +3196,15 @@ table_ref:
append_symbol($2->data.lval, $4); }
*/
| array_dim_ref { /* allow "s1.a1[x][1:2]" */
- $$ = _symbol_create_symbol( SQL_ARRAY, $1);
+ dlist *l = L();
+ append_symbol(l, $1);
+ append_symbol(l, NULL);
+ $$ = _symbol_create_list( SQL_ARRAY, l);
}
| array_dim_ref table_name { /* allow "s1.a1[x][1:2] AS <ident>" */
dlist *l = L();
- l = append_symbol(l, $1);
- l = append_symbol(l, $2);
+ append_symbol(l, $1);
+ append_symbol(l, $2);
$$ = _symbol_create_list( SQL_ARRAY, l);
}
@@ -3248,14 +3252,17 @@ opt_group_by_clause:
/* empty */ { $$ = NULL; }
| sqlGROUP BY column_ref_commalist { $$ = _symbol_create_list( SQL_GROUPBY,
$3 );}
| sqlGROUP BY group_ref_commalist {
+ /*
dlist *l = L();
- l= append_list(l,$3);
- l= append_int(l,0);
+ append_list(l,$3);
+ append_int(l,0);
$$ = _symbol_create_list( SQL_GROUPBY, l );}
+ */
+ $$ = _symbol_create_list( SQL_GROUPBY, append_int($3,0) );}
| sqlGROUP BY DISTINCT group_ref_commalist {
dlist *l = L();
- l= append_list(l,$4);
- l= append_int(l,1);
+ append_list(l,$4);
+ append_int(l,1);
$$ = _symbol_create_list( SQL_GROUPBY, l);}
;
@@ -3266,9 +3273,8 @@ group_ref_commalist:
;
group_item:
- array_dim_ref { $$ = _symbol_create_symbol( SQL_ARRAY_INDEX, $1); }
- | array_cell_ref { $$ = _symbol_create_symbol(SQL_COLUMN, $1); }
-/* | column_ref { $$ = _symbol_create_list(SQL_COLUMN, $1); } */
+ array_dim_ref { $$ = $1; }
+ | array_cell_ref { $$ = $1; }
;
column_ref_commalist:
@@ -3667,8 +3673,8 @@ value_exp:
array_dim_ref:
qname index_exp_list {
dlist *l = L();
- l = append_list(l, $1);
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list