Changeset: 03d82bbe1886 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=03d82bbe1886
Modified Files:
        sql/server/rel_psm.c
        sql/test/subquery/Tests/subquery5.sql
        sql/test/subquery/Tests/subquery5.stable.out
Branch: Jun2020
Log Message:

Fix for return statements on SQL functions. If the return statement is 
returning no rows, the output must be null


diffs (92 lines):

diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -428,6 +428,7 @@ rel_psm_return( sql_query *query, sql_su
        sql_exp *res;
        sql_rel *rel = NULL;
        list *l = sa_list(sql->sa);
+       bool requires_proj = false;
 
        if (restypelist)
                ek.card = card_relation;
@@ -436,13 +437,27 @@ rel_psm_return( sql_query *query, sql_su
        res = rel_value_exp2(query, &rel, return_sym, sql_sel, ek);
        if (!res)
                return NULL;
-       if (!rel && exp_is_rel(res))
+       if (!rel && exp_is_rel(res)) {
                rel = exp_rel_get_rel(sql->sa, res);
+               if (rel && !restypelist && !is_groupby(rel->op)) { /* On 
regular functions return zero or 1 rows for every row */
+                       rel->card = CARD_MULTI; 
+                       rel = rel_zero_or_one(sql, rel, ek);
+                       if (list_length(rel->exps) != 1)
+                               return sql_error(sql, 02, SQLSTATE(42000) 
"RETURN: must return a single column");
+                       res = exp_ref(sql->sa, (sql_exp*) rel->exps->t->data);
+                       requires_proj = true;
+               }
+       }
        if (ek.card != card_relation && (!restype || (res = rel_check_type(sql, 
restype, rel, res, type_equal)) == NULL))
                return (!restype)?sql_error(sql, 02, SQLSTATE(42000) "RETURN: 
return type does not match"):NULL;
        else if (ek.card == card_relation && !rel)
                return NULL;
 
+       if (requires_proj) {
+               rel = rel_project(sql->sa, rel, list_append(sa_list(sql->sa), 
res));
+               res = exp_rel(sql, rel);
+       }
+
        if (rel && !is_ddl(rel->op) && ek.card == card_relation) {
                list *exps = sa_list(sql->sa), *oexps = rel->exps;
                node *n, *m;
diff --git a/sql/test/subquery/Tests/subquery5.sql 
b/sql/test/subquery/Tests/subquery5.sql
--- a/sql/test/subquery/Tests/subquery5.sql
+++ b/sql/test/subquery/Tests/subquery5.sql
@@ -38,10 +38,7 @@ CREATE OR REPLACE FUNCTION evilfunction(
 
 CREATE OR REPLACE FUNCTION evilfunction(input INT) RETURNS INT BEGIN RETURN 
SELECT input, 2; END; --error, more than 1 return
 
-CREATE OR REPLACE FUNCTION evilfunction(input INT) RETURNS INT 
-BEGIN
-       RETURN SELECT input WHERE FALSE;
-END;
+CREATE OR REPLACE FUNCTION evilfunction(input INT) RETURNS INT BEGIN RETURN 
SELECT input WHERE FALSE; END;
 
 SELECT evilfunction(1);
        -- NULL
diff --git a/sql/test/subquery/Tests/subquery5.stable.out 
b/sql/test/subquery/Tests/subquery5.stable.out
--- a/sql/test/subquery/Tests/subquery5.stable.out
+++ b/sql/test/subquery/Tests/subquery5.stable.out
@@ -38,6 +38,33 @@ stdout of test 'subquery5` in directory 
 [ 1234,        40      ]
 [ 1234,        40      ]
 [ 1234,        40      ]
+#CREATE OR REPLACE FUNCTION evilfunction(input INT) RETURNS INT 
+#BEGIN
+#      RETURN SELECT input WHERE FALSE;
+#END;
+#SELECT evilfunction(1);
+% . # table_name
+% %1 # name
+% int # type
+% 1 # length
+[ NULL ]
+#SELECT evilfunction(1);
+% . # table_name
+% %1 # name
+% int # type
+% 1 # length
+[ NULL ]
+#SELECT evilfunction(1), 1;
+% .,   . # table_name
+% %1,  %2 # name
+% int, tinyint # type
+% 1,   1 # length
+[ NULL,        1       ]
+#CREATE OR REPLACE FUNCTION evilfunction(input INT) RETURNS INT 
+#BEGIN
+#      RETURN SELECT input UNION ALL SELECT input;
+#END;
+#DROP FUNCTION evilfunction(INT);
 #DROP TABLE tbl_ProductSales;
 #DROP TABLE another_T;
 #DROP TABLE integers;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to