Changeset: 5537ecbacd92 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5537ecbacd92
Modified Files:
        sql/backends/monet5/sql_gencode.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_select.c
        sql/server/sql_semantic.c
Branch: Nov2019
Log Message:

Backported recent prepared statement fixes into Nov2019 branch


diffs (295 lines):

diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -770,7 +770,7 @@ backend_dumpproc(backend *be, Client c, 
                        sql_type *tpe = a->type.type;
                        int type, varid = 0;
 
-                       if (!tpe) {
+                       if (!tpe || tpe->eclass == EC_ANY) {
                                sql_error(m, 003, SQLSTATE(42000) "Could not 
determine type for argument number %d\n", argc+1);
                                goto cleanup;
                        }
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
@@ -1503,6 +1503,12 @@ exp_is_null(mvc *sql, sql_exp *e )
 }
 
 int
+exp_is_rel( sql_exp *e )
+{
+       return (e && e->type == e_psm && e->flag == PSM_REL && e->l);
+}
+
+int
 exp_is_atom( sql_exp *e )
 {
        switch (e->type) {
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -129,6 +129,7 @@ extern int exp_is_true(mvc *sql, sql_exp
 extern int exp_is_zero(mvc *sql, sql_exp *e);
 extern int exp_is_not_null(mvc *sql, sql_exp *e);
 extern int exp_is_null(mvc *sql, sql_exp *e);
+extern int exp_is_rel(sql_exp *e);
 extern int exps_are_atoms(list *exps);
 extern int exp_has_func(sql_exp *e);
 extern int exp_unsafe(sql_exp *e, int allow_identity);
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
@@ -521,6 +521,9 @@ score_func( sql_subfunc *sf, list *tl)
                sql_arg *a = n->data;
                sql_subtype *t = m->data;
 
+               if (!t)
+                       continue;
+
                if (a->type.type->eclass == EC_ANY)
                        score += 100;
                else if (is_subtype(t, &a->type))
@@ -585,7 +588,7 @@ find_table_function_type(mvc *sql, sql_s
                                        atp = t;
                                        aa = a;
                                }
-                               if (aa && a->type.type->eclass == EC_ANY &&
+                               if (aa && a->type.type->eclass == EC_ANY && t 
&& atp &&
                                    t->type->localtype > atp->type->localtype){
                                        atp = t;
                                        aa = a;
@@ -596,7 +599,7 @@ find_table_function_type(mvc *sql, sql_s
                                sql_exp *e = n->data;
                                sql_subtype *ntp = &a->type;
 
-                               if (a->type.type->eclass == EC_ANY)
+                               if (a->type.type->eclass == EC_ANY && atp)
                                        ntp = sql_create_subtype(sql->sa, 
atp->type, atp->digits, atp->scale);
                                e = rel_check_type(sql, ntp, NULL, e, 
type_equal);
                                if (!e) {
@@ -1249,7 +1252,10 @@ exp_fix_scale(mvc *sql, sql_subtype *ct,
 static int
 rel_set_type_param(mvc *sql, sql_subtype *type, sql_rel *rel, sql_exp 
*rel_exp, int upcast)
 {
-       if (!type || !rel_exp || (rel_exp->type != e_atom && rel_exp->type != 
e_column))
+       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))
                return -1;
 
        /* use largest numeric types */
@@ -1262,15 +1268,37 @@ rel_set_type_param(mvc *sql, sql_subtype
        if (upcast && type->type->eclass == EC_FLT) 
                type = sql_bind_localtype("dbl");
 
-       if ((rel_exp->type == e_atom || rel_exp->type == e_column) && 
(rel_exp->l || rel_exp->r || rel_exp->f)) {
+       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);
-               return rel_set_type_recurse(sql, type, rel, &relname, &expname);
-       } else if (set_type_param(sql, type, rel_exp->flag) == 0) {
-               rel_exp->tpe = *type;
-               return 0;
-       }
-       return -1;
+               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;
+}
+
+static int
+rel_binop_check_types(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, int 
upcast)
+{
+       sql_subtype *t1 = exp_subtype(ls), *t2 = exp_subtype(rs);
+       
+       if (!t1 || !t2) {
+               if (t2 && !t1 && rel_set_type_param(sql, t2, rel, ls, upcast) < 
0)
+                       return -1;
+               if (t1 && !t2 && rel_set_type_param(sql, t1, rel, rs, upcast) < 
0)
+                       return -1;
+       }
+       if (!exp_subtype(ls) && !exp_subtype(rs)) {
+               (void) sql_error(sql, 01, SQLSTATE(42000) "Cannot have a 
parameter (?) on both sides of an expression");
+               return -1;
+       }
+       return 0;
 }
 
 /* try to do an in-place conversion
@@ -1650,8 +1678,6 @@ rel_compare_exp_(sql_query *query, sql_r
 
                        type = (int)swap_compare((comp_type)type);
                }
-               if (!exp_subtype(ls) && !exp_subtype(rs))
-                       return sql_error(sql, 01, SQLSTATE(42000) "Cannot have 
a parameter (?) on both sides of an expression");
                if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, 
type_equal_no_any) < 0)
                        return NULL;
                e = exp_compare(sql->sa, ls, rs, type);
@@ -2023,7 +2049,7 @@ static sql_exp*
                                        atp = t;
                                        aa = a;
                                }
-                               if (aa && a->type.type->eclass == EC_ANY &&
+                               if (aa && a->type.type->eclass == EC_ANY && t 
&& atp &&
                                    t->type->localtype > atp->type->localtype){
                                        atp = t;
                                        aa = a;
@@ -2034,7 +2060,7 @@ static sql_exp*
                                sql_exp *e = n->data;
                                sql_subtype *ntp = &a->type;
 
-                               if (a->type.type->eclass == EC_ANY)
+                               if (a->type.type->eclass == EC_ANY && atp)
                                        ntp = sql_create_subtype(sql->sa, 
atp->type, atp->digits, atp->scale);
                                e = rel_check_type(sql, ntp, rel, e, 
type_equal);
                                if (!e) {
@@ -2049,7 +2075,7 @@ static sql_exp*
                                append(nexps, e);
                        }
                        /* dirty hack */
-                       if (f->res && aa)
+                       if (f->res && aa && atp)
                                f->res->h->data = sql_create_subtype(sql->sa, 
atp->type, atp->digits, atp->scale);
                        if (nexps) 
                                return exp_op(sql->sa, nexps, f);
@@ -2723,12 +2749,24 @@ rel_logical_value_exp(sql_query *query, 
                sql_exp *le = rel_value_exp(query, rel, lo, f, ek);
                sql_exp *re1 = rel_value_exp(query, rel, ro1, f, ek);
                sql_exp *re2 = rel_value_exp(query, rel, ro2, f, ek);
+               sql_subtype *t1, *t2, *t3;
                sql_exp *e1 = NULL, *e2 = NULL;
 
                assert(sc->data.lval->h->next->type == type_int);
                if (!le || !re1 || !re2) 
                        return NULL;
 
+               t1 = exp_subtype(le);
+               t2 = exp_subtype(re1);
+               t3 = exp_subtype(re2);
+
+               if (!t1 && (t2 || t3) && rel_binop_check_types(sql, rel ? *rel 
: NULL, le, t2 ? re1 : re2, 0) < 0)
+                       return NULL;
+               if (!t2 && (t1 || t3) && rel_binop_check_types(sql, rel ? *rel 
: NULL, le, t1 ? le : re2, 0) < 0)
+                       return NULL;
+               if (!t3 && (t1 || t2) && rel_binop_check_types(sql, rel ? *rel 
: NULL, le, t1 ? le : re1, 0) < 0)
+                       return NULL;
+
                if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : 
NULL, &le, &re1, 1, type_equal) < 0 ||
                        rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : 
NULL, &le, &re2, 1, type_equal) < 0)
                        return NULL;
@@ -2741,9 +2779,8 @@ rel_logical_value_exp(sql_query *query, 
                        sql_subfunc *min = sql_bind_func(sql->sa, 
sql->session->schema, "sql_min", exp_subtype(re1), exp_subtype(re2), F_FUNC);
                        sql_subfunc *max = sql_bind_func(sql->sa, 
sql->session->schema, "sql_max", exp_subtype(re1), exp_subtype(re2), F_FUNC);
 
-                       if (!min || !max) {
+                       if (!min || !max)
                                return sql_error(sql, 02, SQLSTATE(42000) "min 
or max operator on types %s %s missing", exp_subtype(re1)->type->sqlname, 
exp_subtype(re2)->type->sqlname);
-                       }
                        tmp = exp_binop(sql->sa, re1, re2, min);
                        re2 = exp_binop(sql->sa, re1, re2, max);
                        re1 = tmp;
@@ -3665,18 +3702,16 @@ rel_binop_(sql_query *query, sql_rel *re
                        if (!t2)
                                rel_set_type_param(sql, 
arg_type(f->func->ops->h->next->data), rel, r, 1);
                        f = NULL;
-               } else {
-                       if (t2 && !t1 && rel_set_type_param(sql, t2, rel, l, 1) 
< 0)
-                               return NULL;
-                       if (t1 && !t2 && rel_set_type_param(sql, t1, rel, r, 1) 
< 0)
-                               return NULL;
-               }
+
+                       if (!exp_subtype(l) || !exp_subtype(r))
+                               return sql_error(sql, 01, SQLSTATE(42000) 
"Cannot have a parameter (?) on both sides of an expression");
+               } else if (rel_binop_check_types(sql, rel, l, r, 1) < 0)
+                       return NULL;
+
                t1 = exp_subtype(l);
                t2 = exp_subtype(r);
-       }
-
-       if (!t1 || !t2)
-               return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a 
parameter (?) on both sides of an expression");
+               assert(t1 && t2);
+       }
 
        if (!f && (is_addition(fname) || is_subtraction(fname)) && 
                ((t1->type->eclass == EC_NUM && t2->type->eclass == EC_NUM) ||
@@ -4503,8 +4538,6 @@ rel_case(sql_query *query, sql_rel **rel
                else
                        dn = dn->next;
        }
-       if (!restype) 
-               return sql_error(sql, 02, SQLSTATE(42000) "result type 
missing");
        /* for COALESCE we skip the last (else part) */
        for (; dn && (token != SQL_COALESCE || dn->next); dn = dn->next) {
                sql_exp *cond = NULL, *result = NULL;
@@ -4537,10 +4570,12 @@ rel_case(sql_query *query, sql_rel **rel
                list_prepend(results, result);
 
                tpe = exp_subtype(result);
-               if (!tpe) 
-                       return sql_error(sql, 02, SQLSTATE(42000) "result type 
missing");
-               supertype(&rtype, restype, tpe);
-               restype = &rtype;
+               if (tpe && restype) {
+                       supertype(&rtype, restype, tpe);
+                       restype = &rtype;
+               } else if (tpe) {
+                       restype = tpe;
+               }
        }
        if (opt_else || else_exp) {
                sql_exp *result = else_exp;
@@ -4551,9 +4586,13 @@ rel_case(sql_query *query, sql_rel **rel
                tpe = exp_subtype(result);
                if (tpe && restype) {
                        supertype(&rtype, restype, tpe);
-                       tpe = &rtype;
-               }
-               restype = tpe;
+                       restype = &rtype;
+               } else if (tpe) {
+                       restype = tpe;
+               }
+
+               if (!restype)
+                       return sql_error(sql, 02, SQLSTATE(42000) "Result type 
missing");
                if (restype->type->localtype == TYPE_void) /* NULL */
                        restype = sql_bind_localtype("str");
 
@@ -4564,6 +4603,8 @@ rel_case(sql_query *query, sql_rel **rel
                if (!res) 
                        return NULL;
        } else {
+               if (!restype)
+                       return sql_error(sql, 02, SQLSTATE(42000) "Result type 
missing");
                if (restype->type->localtype == TYPE_void) /* NULL */
                        restype = sql_bind_localtype("str");
                res = exp_null(sql->sa, restype);
diff --git a/sql/server/sql_semantic.c b/sql/server/sql_semantic.c
--- a/sql/server/sql_semantic.c
+++ b/sql/server/sql_semantic.c
@@ -190,12 +190,10 @@ qname_catalog(dlist *qname)
 
        if (dlist_length(qname) == 3) {
                return qname->h->data.sval;
-       } 
-
+       }
        return NULL;
 }
 
-
 int
 set_type_param(mvc *sql, sql_subtype *type, int nr)
 {
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to