Changeset: 67b5fda62ad6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=67b5fda62ad6
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_select.c
        sql/server/sql_semantic.c
        sql/test/miscellaneous/Tests/groupby_error.sql
        sql/test/miscellaneous/Tests/groupby_error.stable.err
        sql/test/miscellaneous/Tests/groupby_error.stable.out
Branch: linear-hashing
Log Message:

merged


diffs (truncated from 489 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
@@ -782,7 +782,8 @@ exp_rel(mvc *sql, sql_rel *rel)
        assert(rel);
        if (is_project(rel->op)) {
                sql_exp *last = rel->exps->t->data;
-               e->tpe = *exp_subtype(last);
+               sql_subtype *t = exp_subtype(last);
+               e->tpe = t ? *t : (sql_subtype) {0};
        }
        return e;
 }
@@ -1707,7 +1708,7 @@ exp_is_atom( sql_exp *e )
 int
 exp_is_rel( sql_exp *e )
 {
-       return (e->type == e_psm && e->flag == PSM_REL && e->l);
+       return (e && e->type == e_psm && e->flag == PSM_REL && e->l);
 }
 
 int
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
@@ -1251,7 +1251,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 */
@@ -1264,15 +1267,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
@@ -1613,6 +1638,8 @@ rel_compare_exp_(sql_query *query, sql_r
                        if (anti)
                                set_anti(e);
                } else {
+                       if (rel_binop_check_types(sql, rel, ls, rs, 0) < 0)
+                               return NULL;
                        e = exp_compare_func(sql, ls, rs, rs2, 
compare_func((comp_type)type, quantifier?0:anti), quantifier);
                        if (anti && quantifier)
                                e = rel_unop_(sql, NULL, e, NULL, "not", 
card_value);
@@ -1631,8 +1658,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);
@@ -1802,8 +1827,6 @@ rel_compare(sql_query *query, sql_rel *r
                if (!rs2)
                        return NULL;
        }
-       if (!rs) 
-               return NULL;
        if (ls->card > rs->card && rs->card == CARD_AGGR && is_sql_having(f))
                return sql_error(sql, 05, SQLSTATE(42000) "SELECT: cannot use 
non GROUP BY column '%s.%s' in query results without an aggregate function", 
exp_relname(ls), exp_name(ls));
        if (rs->card > ls->card && ls->card == CARD_AGGR && is_sql_having(f))
@@ -1903,18 +1926,25 @@ static sql_exp*
 }
 
 static sql_exp *
-exp_exist(sql_query *query, sql_exp *le, int exists)
+exp_exist(sql_query *query, sql_rel *rel, sql_exp *le, int exists)
 {
        mvc *sql = query->sql;
        sql_subfunc *exists_func = NULL;
-                       
+       sql_subtype *t;
+
+       if (!exp_name(le))
+               exp_label(sql->sa, le, ++sql->label);
+       if (!exp_subtype(le) && rel_set_type_param(sql, 
sql_bind_localtype("bit"), rel, le, 0) < 0) /* workaround */
+               return NULL;
+       t = exp_subtype(le);
+
        if (exists)
-               exists_func = sql_bind_func(sql->sa, sql->session->schema, 
"sql_exists", exp_subtype(le), NULL, F_FUNC);
+               exists_func = sql_bind_func(sql->sa, sql->session->schema, 
"sql_exists", t, NULL, F_FUNC);
        else
-               exists_func = sql_bind_func(sql->sa, sql->session->schema, 
"sql_not_exists", exp_subtype(le), NULL, F_FUNC);
+               exists_func = sql_bind_func(sql->sa, sql->session->schema, 
"sql_not_exists", t, NULL, F_FUNC);
 
        if (!exists_func) 
-               return sql_error(sql, 02, SQLSTATE(42000) "exist operator on 
type %s missing", exp_subtype(le)->type->sqlname);
+               return sql_error(sql, 02, SQLSTATE(42000) "exist operator on 
type %s missing", t->type->sqlname);
        return exp_unop(sql->sa, le, exists_func);
 }
 
@@ -1927,7 +1957,7 @@ rel_exists_value_exp(sql_query *query, s
        le = rel_value_exp(query, rel, sc->data.sym, f, ek);
        if (!le) 
                return NULL;
-       e = exp_exist(query, le, sc->token == SQL_EXISTS);
+       e = exp_exist(query, rel ? *rel : NULL, le, sc->token == SQL_EXISTS);
        if (e) {
                /* only freevar should have CARD_AGGR */
                e->card = CARD_ATOM;
@@ -1950,7 +1980,7 @@ rel_exists_exp(sql_query *query, sql_rel
        assert(!is_sql_sel(f));
        if (sq) {
                sql_exp *e = exp_rel(sql, sq);
-               e = exp_exist(query, e, sc->token == SQL_EXISTS);
+               e = exp_exist(query, rel, e, sc->token == SQL_EXISTS);
                if (e) {
                        /* only freevar should have CARD_AGGR */
                        e->card = CARD_ATOM;
@@ -1992,6 +2022,7 @@ rel_in_value_exp(sql_query *query, sql_r
                le = ll->h->data;
        } else {
                le = exp_values(sql->sa, ll);
+               exp_label(sql->sa, le, ++sql->label);
                ek.card = card_relation;
                is_tuple = 1;
        }
@@ -2015,8 +2046,23 @@ rel_in_value_exp(sql_query *query, sql_r
                }
 
                values = exp_values(sql->sa, vals);
-               if (!is_tuple) /* if it's not a tuple, enforce coersion on the 
type for every element on the list */
+               exp_label(sql->sa, values, ++sql->label);
+               if (is_tuple) { 
+                       sql_exp *e_rel = (sql_exp *) vals->h->data;
+                       list *le_vals = le->f, *rel_vals = 
((sql_rel*)e_rel->l)->exps;
+
+                       for (node *m = le_vals->h, *o = rel_vals->h ; m && o ; 
m = m->next, o = o->next) {
+                               sql_exp *e = m->data, *f = o->data;
+
+                               if (rel_binop_check_types(sql, rel ? *rel : 
NULL, e, f, 0) < 0)
+                                       return NULL;
+                       }
+               } else { /* if it's not a tuple, enforce coersion on the type 
for every element on the list */
                        values = exp_values_set_supertype(sql, values);
+
+                       if (rel_binop_check_types(sql, rel ? *rel : NULL, le, 
values, 0) < 0)
+                               return NULL;
+               }
                e = exp_in_func(sql, le, values, (sc->token == SQL_IN), 
is_tuple);
        }
        if (e && le)
@@ -2157,6 +2203,9 @@ rel_logical_value_exp(sql_query *query, 
                rs = rel_value_exp(query, rel, ro, f, ek);
                if (!rs)
                        return NULL;
+
+               if (rel_binop_check_types(sql, rel ? *rel : NULL, ls, rs, 0) < 
0)
+                       return NULL;
                ls = exp_compare_func(sql, ls, rs, NULL, 
compare_func(compare_str2type(compare_op), quantifier?0:need_not), quantifier);
                if (need_not && quantifier)
                        ls = rel_unop_(sql, NULL, ls, NULL, "not", card_value);
@@ -2487,12 +2536,24 @@ rel_logical_exp(sql_query *query, sql_re
                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;
                int flag = 0;
 
                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, le, t2 
? re1 : re2, 0) < 0)
+                       return NULL;
+               if (!t2 && (t1 || t3) && rel_binop_check_types(sql, rel, le, t1 
? le : re2, 0) < 0)
+                       return NULL;
+               if (!t3 && (t1 || t2) && rel_binop_check_types(sql, rel, le, t1 
? le : re1, 0) < 0)
+                       return NULL;
+
                if (rel_convert_types(sql, rel, rel, &le, &re1, 1, type_equal) 
< 0 ||
                    rel_convert_types(sql, rel, rel, &le, &re2, 1, type_equal) 
< 0)
                        return NULL;
@@ -2506,9 +2567,8 @@ rel_logical_exp(sql_query *query, sql_re
                        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;
@@ -2793,18 +2853,12 @@ rel_binop_(mvc *sql, sql_rel *rel, sql_e
                        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;
-               }
-               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");
+
+                       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;
+       }
 
        if (!f && (is_addition(fname) || is_subtraction(fname)) && 
                ((t1->type->eclass == EC_NUM && t2->type->eclass == EC_NUM) ||
@@ -5279,7 +5333,7 @@ rel_select_exp(sql_query *query, sql_rel
                list *te = NULL;
                sql_exp *ce = rel_column_exp(query, &inner, n->data.sym, 
sql_sel | group_totals);
 
-               if (ce && exp_subtype(ce)) {
+               if (ce && (exp_subtype(ce) || (ce->type == e_atom && !ce->l && 
!ce->f))) {
                        pexps = append(pexps, ce);
                        rel = inner;
                        continue;
@@ -5647,7 +5701,6 @@ rel_joinquery_(sql_query *query, sql_rel
 static sql_rel *
 rel_joinquery(sql_query *query, sql_rel *rel, symbol *q)
 {
-
        dnode *n = q->data.lval->h;
        symbol *tab_ref1 = n->data.sym;
        int natural = n->next->data.i_val;
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
@@ -192,12 +192,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)
 {
diff --git a/sql/test/miscellaneous/Tests/groupby_error.sql 
b/sql/test/miscellaneous/Tests/groupby_error.sql
--- a/sql/test/miscellaneous/Tests/groupby_error.sql
+++ b/sql/test/miscellaneous/Tests/groupby_error.sql
@@ -6,10 +6,36 @@ SELECT parent."sys_id" FROM "kagami_dump
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to