Changeset: 69d678706fd0 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/69d678706fd0
Added Files:
sql/test/prepare/Tests/prepare-insert-into.SQL.py
sql/test/prepare/Tests/prepare-insert-into.sql
sql/test/prepare/Tests/prepare-insert-into.stable.out
Modified Files:
sql/server/rel_exp.c
sql/server/rel_exp.h
sql/server/rel_select.c
sql/test/prepare/Tests/All
Branch: Jan2022
Log Message:
Improve parameter type set and cleanup (it was a bit messy). Propagation under
set relations not done yet, but not important
diffs (truncated from 548 to 300 lines):
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -3008,13 +3008,56 @@ exps_reset_freevar(list *exps)
}
}
-int
-rel_set_type_param(mvc *sql, sql_subtype *type, sql_rel *rel, sql_exp
*rel_exp, int upcast)
+static int rel_find_parameter(mvc *sql, sql_subtype *type, sql_rel *rel, const
char *relname, const char *expname);
+
+static int
+set_exp_type(mvc *sql, sql_subtype *type, sql_rel *rel, sql_exp *e)
{
- sql_rel *r = rel;
- int is_rel = exp_is_rel(rel_exp);
-
- if (!type || !rel_exp || (rel_exp->type != e_atom && rel_exp->type !=
e_column && !is_rel))
+ if (mvc_highwater(sql)) {
+ (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex:
running out of stack space");
+ return -1;
+ }
+ if (e->tpe.type)
+ return 0;
+
+ if (e->type == e_column) {
+ const char *nrname = (const char*) e->l, *nename = (const
char*) e->r;
+ /* find all the column references and set the type */
+ if (rel_find_parameter(sql, type, rel, nrname, nename) < 0)
+ return -1;
+ e->tpe = *type;
+ } else if (e->type == e_atom && e->f) {
+ list *atoms = e->f;
+ if (!list_empty(atoms))
+ for (node *n = atoms->h; n; n = n->next)
+ if (set_exp_type(sql, type, rel, n->data) < 0)
/* set recursively */
+ return -1;
+ e->tpe = *type;
+ } else if (e->type == e_atom && !e->l && !e->r && !e->f) {
+ if (set_type_param(sql, type, e->flag) != 0)
+ return -1;
+ e->tpe = *type;
+ } else if (exp_is_rel(e)) { /* for relation expressions, restart cycle
*/
+ rel = (sql_rel*) e->l;
+ /* limiting to these cases */
+ if (!is_project(rel->op) || list_length(rel->exps) != 1)
+ return 0;
+ sql_exp *re = rel->exps->h->data;
+
+ if (set_exp_type(sql, type, rel, re) < 0) /* set recursively */
+ return -1;
+ e->tpe = *type;
+ }
+ return 0;
+}
+
+int
+rel_set_type_param(mvc *sql, sql_subtype *type, sql_rel *rel, sql_exp *exp,
int upcast)
+{
+ sql_exp *e = exp;
+ int is_rel = exp_is_rel(exp);
+
+ if (!type || !exp || (exp->type != e_atom && exp->type != e_column &&
!is_rel))
return -1;
/* use largest numeric types */
@@ -3024,22 +3067,10 @@ rel_set_type_param(mvc *sql, sql_subtype
#else
type = sql_bind_localtype("lng");
#endif
- if (upcast && type->type->eclass == EC_FLT)
+ else if (upcast && type->type->eclass == EC_FLT)
type = sql_bind_localtype("dbl");
- if (is_rel)
- r = (sql_rel*) rel_exp->l;
-
- if ((rel_exp->type == e_atom && (rel_exp->l || rel_exp->r ||
rel_exp->f)) || rel_exp->type == e_column || is_rel) {
- /* it's not a parameter set possible parameters below */
- const char *relname = exp_relname(rel_exp), *expname =
exp_name(rel_exp);
- if (rel_set_type_recurse(sql, type, r, &relname, &expname) < 0)
- return -1;
- } else if (set_type_param(sql, type, rel_exp->flag) != 0)
- return -1;
-
- rel_exp->tpe = *type;
- return 0;
+ return set_exp_type(sql, type, rel, e);
}
/* try to do an in-place conversion
@@ -3192,199 +3223,96 @@ exp_values_set_supertype(mvc *sql, sql_e
}
static int
-exp_set_list_recurse(mvc *sql, sql_subtype *type, sql_exp *e, const char
**relname, const char** expname)
-{
- if (mvc_highwater(sql)) {
- (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex:
running out of stack space");
- return -1;
- }
- assert(*relname && *expname);
- if (!e)
- return 0;
-
- if (exp_is_rel(e)) {
- /* Try to set parameters on the list of projections of the
subquery. For now I won't go any further, ugh */
- sql_rel *r = exp_rel_get_rel(sql->sa, e);
- if ((is_simple_project(r->op) || is_groupby(r->op)) &&
list_length(r->exps) == 1) {
- for (node *n = r->exps->h; n; n = n->next)
- if (exp_set_list_recurse(sql, type, (sql_exp *)
n->data, relname, expname) < 0)
- return -1;
- }
- } else if (e->type == e_atom) {
- if (e->f) {
- const char *next_rel = exp_relname(e), *next_exp =
exp_name(e);
- if (next_rel && next_exp && !strcmp(next_rel, *relname)
&& !strcmp(next_exp, *expname))
- for (node *n = ((list *) e->f)->h; n; n =
n->next)
- if (exp_set_list_recurse(sql, type,
(sql_exp *) n->data, relname, expname) < 0)
- return -1;
- }
- if (e->f && !e->tpe.type) {
- e->tpe = *type;
- } else if (!e->l && !e->r && !e->f && !e->tpe.type) {
- if (set_type_param(sql, type, e->flag) == 0)
- e->tpe = *type;
- else
- return -1;
- }
- }
- return 0;
-}
-
-static int
-exp_set_type_recurse(mvc *sql, sql_subtype *type, sql_exp *e, const char
**relname, const char** expname)
+rel_find_parameter(mvc *sql, sql_subtype *type, sql_rel *rel, const char
*relname, const char *expname)
{
if (mvc_highwater(sql)) {
(void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex:
running out of stack space");
return -1;
}
- assert(*relname && *expname);
- if (!e)
- return 0;
-
- switch (e->type) {
- case e_atom: {
- const char *next_exp = exp_name(e);
- if (e->f || !next_exp || !strcmp(next_exp, *expname)) {
- if (!e->f && next_exp)
- *expname = next_exp;
- return exp_set_list_recurse(sql, type, e,
relname, expname);
- }
- } break;
- case e_convert:
- case e_column: {
- /* if the column pretended is found, set its type */
- const char *next_rel = exp_relname(e), *next_exp =
exp_name(e);
- if (next_rel && *relname && !strcmp(next_rel,
*relname)) {
- *relname = (e->type == e_column && e->l) ?
(const char*) e->l : next_rel;
- if (next_exp && !strcmp(next_exp, *expname)) {
- *expname = (e->type == e_column &&
e->r) ? (const char*) e->r : next_exp;
- if (e->type == e_column &&
!e->tpe.type) {
- if (set_type_param(sql, type,
e->flag) == 0)
- e->tpe = *type;
- else
- return -1;
- }
- }
- }
- if (e->type == e_convert)
- exp_set_type_recurse(sql, type, e->l, relname,
expname);
- } break;
- case e_psm: {
- if (e->flag & PSM_RETURN) {
- for(node *n = ((list*)e->r)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- } else if (e->flag & PSM_WHILE) {
- exp_set_type_recurse(sql, type, e->l, relname,
expname);
- for(node *n = ((list*)e->r)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- } else if (e->flag & PSM_IF) {
- exp_set_type_recurse(sql, type, e->l, relname,
expname);
- for(node *n = ((list*)e->r)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- if (e->f)
- for(node *n = ((list*)e->f)->h ; n ; n
= n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- } else if (e->flag & PSM_REL) {
- rel_set_type_recurse(sql, type, e->l, relname,
expname);
- } else if (e->flag & PSM_EXCEPTION) {
- exp_set_type_recurse(sql, type, e->l, relname,
expname);
- }
- } break;
- case e_aggr:
- case e_func: {
- if (e->l)
- for(node *n = ((list*)e->l)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- if (e->type == e_func && e->r)
- for(node *n = ((list*)e->r)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- } break;
- case e_cmp: {
- if (e->flag == cmp_in || e->flag == cmp_notin) {
- exp_set_type_recurse(sql, type, e->l, relname,
expname);
- for(node *n = ((list*)e->r)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- } else if (e->flag == cmp_or || e->flag == cmp_filter) {
- for(node *n = ((list*)e->l)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- for(node *n = ((list*)e->r)->h ; n ; n =
n->next)
- exp_set_type_recurse(sql, type,
(sql_exp*) n->data, relname, expname);
- } else {
- if(e->l)
- exp_set_type_recurse(sql, type, e->l,
relname, expname);
- if(e->r)
- exp_set_type_recurse(sql, type, e->r,
relname, expname);
- if(e->f)
- exp_set_type_recurse(sql, type, e->f,
relname, expname);
- }
- } break;
- }
- return 0;
-}
-
-int
-rel_set_type_recurse(mvc *sql, sql_subtype *type, sql_rel *rel, const char
**relname, const char **expname)
-{
- if (mvc_highwater(sql)) {
- (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex:
running out of stack space");
- return -1;
- }
- assert(*relname && *expname);
if (!rel)
return 0;
- if (rel->exps)
- for (node *n = rel->exps->h; n; n = n->next)
- exp_set_type_recurse(sql, type, (sql_exp*) n->data,
relname, expname);
+ const char *nrname = relname, *nename = expname;
+ if ((is_simple_project(rel->op) || is_groupby(rel->op)) &&
!list_empty(rel->exps)) {
+ sql_exp *e = NULL;
+
+ if (nrname && nename) { /* find the column reference and
propagate type setting */
+ e = exps_bind_column2(rel->exps, nrname, nename, NULL);
+ } else if (nename) {
+ e = exps_bind_column(rel->exps, nename, NULL, NULL, 1);
+ }
+ if (!e)
+ return 0;
+ /* set order by column types */
+ if (is_simple_project(rel->op) && !list_empty(rel->r)) {
+ sql_exp *ordere = NULL;
+ if (nrname && nename) {
+ ordere = exps_bind_column2(rel->r, nrname,
nename, NULL);
+ } else if (nename) {
+ ordere = exps_bind_column(rel->r, nename, NULL,
NULL, 1);
+ }
+ if (ordere && ordere->type == e_column)
+ ordere->tpe = *type;
+ }
+ if (e->type == e_column) {
+ nrname = (const char*) e->l;
+ nename = (const char*) e->r;
+ e->tpe = *type;
+ } else if ((e->type == e_atom || exp_is_rel(e)) &&
set_exp_type(sql, type, rel, e) < 0) {
+ return -1; /* don't search further */
+ }
+ /* group by columns can have aliases! */
+ if (is_groupby(rel->op) && !list_empty(rel->r)) {
+ if (nrname && nename) {
+ e = exps_bind_column2(rel->r, nrname, nename,
NULL);
+ } else if (nename) {
+ e = exps_bind_column(rel->r, nename, NULL,
NULL, 1);
+ }
+ if (e && e->type == e_column) {
+ nrname = (const char*) e->l;
+ nename = (const char*) e->r;
+ e->tpe = *type;
+ } else if (e && (e->type == e_atom || exp_is_rel(e)) &&
set_exp_type(sql, type, rel, e) < 0) {
+ return -1; /* don't search further */
+ }
+ }
+ if (!e || e->type != e_column)
+ return 0; /* don't search further */
+ }
switch (rel->op) {
- case op_basetable:
- case op_truncate:
- break;
- case op_table:
- if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag ==
TABLE_FROM_RELATION)
- if (rel->l)
- rel_set_type_recurse(sql, type, rel->l,
relname, expname);
- break;
case op_join:
case op_left:
case op_right:
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]