Changeset: 28e02819984d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=28e02819984d
Modified Files:
        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:

Make prepared statements work with the BETWEEN and EXISTS operators


diffs (205 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
@@ -1827,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))
@@ -1928,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);
 }
 
@@ -1952,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;
@@ -1975,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;
@@ -2531,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;
@@ -2550,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;
@@ -5685,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,8 +192,7 @@ qname_catalog(dlist *qname)
 
        if (dlist_length(qname) == 3) {
                return qname->h->data.sval;
-       } 
-
+       }
        return NULL;
 }
 
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
@@ -24,7 +24,15 @@ prepare select col0 from tab0 where (col
 prepare select ? < ANY (select max(col0) from tab0) from tab0 t1;
 prepare select col0 = ALL (select ? from tab0) from tab0 t1;
 
+prepare select 1 from tab0 where 1 between ? and ?;
+prepare select 1 from tab0 where ? between 1 and ?;
+prepare select 1 from tab0 where ? between ? and 1;
+
+prepare select EXISTS (SELECT ? FROM tab0) from tab0;
+prepare select EXISTS (SELECT ?,? FROM tab0) from tab0;
+
 prepare select col0 from tab0 where (?) in (?); --error
+prepare select ? = ALL (select ? from tab0) from tab0 t1; --error
 
 CREATE TABLE tab1(col0 INTEGER, col1 STRING);
 prepare select 1 from tab1 where (col0,col1) in (select ?,? from tab1);
diff --git a/sql/test/miscellaneous/Tests/groupby_error.stable.err 
b/sql/test/miscellaneous/Tests/groupby_error.stable.err
--- a/sql/test/miscellaneous/Tests/groupby_error.stable.err
+++ b/sql/test/miscellaneous/Tests/groupby_error.stable.err
@@ -35,6 +35,10 @@ MAPI  = (monetdb) /var/tmp/mtest-19682/.
 QUERY = prepare select col0 from tab0 where (?) in (?); --error
 ERROR = !Cannot have a parameter (?) on both sides of an expression
 CODE  = 42000
+MAPI  = (monetdb) /var/tmp/mtest-54771/.s.monetdb.35007
+QUERY = prepare select ? = ALL (select ? from tab0) from tab0 t1; --error
+ERROR = !Cannot have a parameter (?) on both sides of an expression
+CODE  = 42000
 
 # 10:56:47 >  
 # 10:56:47 >  "Done."
diff --git a/sql/test/miscellaneous/Tests/groupby_error.stable.out 
b/sql/test/miscellaneous/Tests/groupby_error.stable.out
--- a/sql/test/miscellaneous/Tests/groupby_error.stable.out
+++ b/sql/test/miscellaneous/Tests/groupby_error.stable.out
@@ -153,6 +153,50 @@ stdout of test 'groupby_error` in direct
 % 7,   2,      1,      0,      2,      2 # length
 [ "boolean",   1,      0,      "",     "%5",   "%5"    ]
 [ "int",       32,     0,      NULL,   NULL,   NULL    ]
+#prepare select 1 from tab0 where 1 between ? and ?;
+#prepare select 1 from tab0 where 1 between ? and ?;
+% .prepare,    .prepare,       .prepare,       .prepare,       .prepare,       
.prepare # table_name
+% type,        digits, scale,  schema, table,  column # name
+% varchar,     int,    int,    str,    str,    str # type
+% 7,   1,      1,      0,      0,      0 # length
+[ "tinyint",   1,      0,      "",     "",     ""      ]
+[ "tinyint",   1,      0,      NULL,   NULL,   NULL    ]
+[ "tinyint",   1,      0,      NULL,   NULL,   NULL    ]
+#prepare select 1 from tab0 where ? between 1 and ?;
+#prepare select 1 from tab0 where ? between 1 and ?;
+% .prepare,    .prepare,       .prepare,       .prepare,       .prepare,       
.prepare # table_name
+% type,        digits, scale,  schema, table,  column # name
+% varchar,     int,    int,    str,    str,    str # type
+% 7,   1,      1,      0,      0,      0 # length
+[ "tinyint",   1,      0,      "",     "",     ""      ]
+[ "tinyint",   1,      0,      NULL,   NULL,   NULL    ]
+[ "tinyint",   1,      0,      NULL,   NULL,   NULL    ]
+#prepare select 1 from tab0 where ? between ? and 1;
+#prepare select 1 from tab0 where ? between ? and 1;
+% .prepare,    .prepare,       .prepare,       .prepare,       .prepare,       
.prepare # table_name
+% type,        digits, scale,  schema, table,  column # name
+% varchar,     int,    int,    str,    str,    str # type
+% 7,   1,      1,      0,      0,      0 # length
+[ "tinyint",   1,      0,      "",     "",     ""      ]
+[ "tinyint",   1,      0,      NULL,   NULL,   NULL    ]
+[ "tinyint",   1,      0,      NULL,   NULL,   NULL    ]
+#prepare select EXISTS (SELECT ? FROM tab0) from tab0;
+#prepare select EXISTS (SELECT ? FROM tab0) from tab0;
+% .prepare,    .prepare,       .prepare,       .prepare,       .prepare,       
.prepare # table_name
+% type,        digits, scale,  schema, table,  column # name
+% varchar,     int,    int,    str,    str,    str # type
+% 7,   1,      1,      0,      2,      2 # length
+[ "boolean",   1,      0,      "",     "%2",   "%2"    ]
+[ "boolean",   1,      0,      NULL,   NULL,   NULL    ]
+#prepare select EXISTS (SELECT ?,? FROM tab0) from tab0;
+#prepare select EXISTS (SELECT ?,? FROM tab0) from tab0;
+% .prepare,    .prepare,       .prepare,       .prepare,       .prepare,       
.prepare # table_name
+% type,        digits, scale,  schema, table,  column # name
+% varchar,     int,    int,    str,    str,    str # type
+% 7,   1,      1,      0,      2,      2 # length
+[ "boolean",   1,      0,      "",     "%3",   "%3"    ]
+[ "boolean",   1,      0,      NULL,   NULL,   NULL    ]
+[ "boolean",   1,      0,      NULL,   NULL,   NULL    ]
 #CREATE TABLE tab1(col0 INTEGER, col1 STRING);
 #prepare select 1 from tab1 where (col0,col1) in (select ?,? from tab1);
 #prepare select 1 from tab1 where (col0,col1) in (select ?,? from tab1);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to