Changeset: 99104d1e23cf for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=99104d1e23cf
Modified Files:
        sql/server/rel_select.c
        sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
        
sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
        
sql/test/BugTracker-2017/Tests/udf_crash_subquery_scalar_paramters.Bug-6399.stable.err
Branch: Nov2019
Log Message:

Improving error handeling of table returned functions. We either allow a single 
subquery, or a list of values

Previously violating this contraint, would give an error message saying the 
function didn't exist, which was wrong.


diffs (189 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
@@ -672,8 +672,8 @@ rel_named_table_function(sql_query *quer
        sql_rel *sq = NULL, *outer = NULL;
        sql_exp *e = NULL;
        sql_subfunc *sf = NULL;
-       symbol *sym = ast->data.lval->h->data.sym;
-       dnode *l = sym->data.lval->h;
+       symbol *sym = ast->data.lval->h->data.sym, *subquery = NULL;
+       dnode *l = sym->data.lval->h, *n;
        char *tname = NULL;
        char *fname = qname_fname(l->data.lval); 
        char *sname = qname_schema(l->data.lval);
@@ -684,37 +684,42 @@ rel_named_table_function(sql_query *quer
                return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: no such 
schema '%s'", sname);
 
        tl = sa_list(sql->sa);
-       exps = new_exp_list(sql->sa);
+       exps = sa_list(sql->sa);
        if (l->next) { /* table call with subquery */
-               symtype next_sim = l->next->type;
-               if ((next_sim == type_symbol && l->next->data.sym->token == 
SQL_SELECT) || (next_sim == type_list && l->next->data.lval->h->data.sym->token 
== SQL_SELECT)) {
-                       dnode *nn = next_sim == type_symbol ? l->next->next : 
l->next->data.lval->h->next;
-                       symbol *nsym = next_sim == type_symbol ? 
l->next->data.sym : l->next->data.lval->h->data.sym;
-
-                       if (nn != NULL)
-                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: The input for the table returning function '%s' must be either a 
single sub query, or a list of values", fname);
-                       if (!(sq = rel_subquery(query, NULL, nsym, ek)))
-                               return NULL;
-               } else if (next_sim == type_symbol || next_sim == type_list) {
-                       dnode *n;
+               if (l->next->type == type_symbol || l->next->type == type_list) 
{
                        exp_kind iek = {type_value, card_column, TRUE};
                        list *exps = sa_list(sql->sa);
-
-                       if (next_sim == type_symbol)
+                       int count = 0;
+
+                       if (l->next->type == type_symbol)
                                n = l->next;
-                       else 
+                       else
                                n = l->next->data.lval->h;
-                       for ( ; n; n = n->next) {
-                               sql_exp *e = rel_value_exp(query, &outer, 
n->data.sym, sql_sel, iek);
-
-                               if (!e)
+
+                       for (dnode *m = n; m; m = m->next) {
+                               if (m->type == type_symbol && 
m->data.sym->token == SQL_SELECT)
+                                       subquery = m->data.sym;
+                               count++;
+                       }
+                       if (subquery && count > 1)
+                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: The input for the table returning function '%s' must be either a 
single sub query, or a list of values", fname);
+
+                       if (subquery) {
+                               if (!(sq = rel_subquery(query, NULL, subquery, 
ek)))
                                        return NULL;
-                               append(exps, e);
-                       }
-                       sq = rel_project(sql->sa, NULL, exps);
-                       if (lateral && outer) {
-                               sq = rel_crossproduct(sql->sa, sq, outer, 
op_join);
-                               set_dependent(sq);
+                       } else {
+                               for ( ; n; n = n->next) {
+                                       sql_exp *e = rel_value_exp(query, 
&outer, n->data.sym, sql_sel, iek);
+
+                                       if (!e)
+                                               return NULL;
+                                       append(exps, e);
+                               }
+                               sq = rel_project(sql->sa, NULL, exps);
+                               if (lateral && outer) {
+                                       sq = rel_crossproduct(sql->sa, sq, 
outer, op_join);
+                                       set_dependent(sq);
+                               }
                        }
                }
                if (!sq || (!lateral && outer))
@@ -6925,8 +6930,8 @@ rel_loader_function(sql_query *query, sy
        exp_kind ek = { type_value, card_relation, TRUE };
        sql_rel *sq = NULL;
        sql_exp *e = NULL;
-       symbol *sym = fcall;
-       dnode *l = sym->data.lval->h;
+       symbol *sym = fcall, *subquery = NULL;
+       dnode *l = sym->data.lval->h, *n;
        char *sname = qname_schema(l->data.lval);
        char *fname = qname_fname(l->data.lval);
        char *tname = NULL;
@@ -6938,34 +6943,39 @@ rel_loader_function(sql_query *query, sy
                return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: no such 
schema '%s'", sname);
 
        tl = sa_list(sql->sa);
-       exps = new_exp_list(sql->sa);
+       exps = sa_list(sql->sa);
        if (l->next) { /* table call with subquery */
-               symtype next_sim = l->next->type;
-               if ((next_sim == type_symbol && l->next->data.sym->token == 
SQL_SELECT) || (next_sim == type_list && l->next->data.lval->h->data.sym->token 
== SQL_SELECT)) {
-                       dnode *nn = next_sim == type_symbol ? l->next->next : 
l->next->data.lval->h->next;
-                       symbol *nsym = next_sim == type_symbol ? 
l->next->data.sym : l->next->data.lval->h->data.sym;
-
-                       if (nn != NULL)
-                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: The input for the loader function '%s' must be either a single sub 
query, or a list of values", fname);
-                       if (!(sq = rel_subquery(query, NULL, nsym, ek)))
-                               return NULL;
-               } else if (next_sim == type_symbol || next_sim == type_list) {
-                       dnode *n;
+               if (l->next->type == type_symbol || l->next->type == type_list) 
{
                        exp_kind iek = {type_value, card_column, TRUE};
-                       list *exps = sa_list (sql->sa);
+                       list *exps = sa_list(sql->sa);
+                       int count = 0;
 
                        if (l->next->type == type_symbol)
                                n = l->next;
-                       else 
+                       else
                                n = l->next->data.lval->h;
-                       for ( ; n; n = n->next) {
-                               sql_exp *e = rel_value_exp(query, NULL, 
n->data.sym, sql_sel, iek);
-
-                               if (!e)
+
+                       for (dnode *m = n; m; m = m->next) {
+                               if (m->type == type_symbol && 
m->data.sym->token == SQL_SELECT)
+                                       subquery = m->data.sym;
+                               count++;
+                       }
+                       if (subquery && count > 1)
+                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: The input for the loader function '%s' must be either a single sub 
query, or a list of values", fname);
+
+                       if (subquery) {
+                               if (!(sq = rel_subquery(query, NULL, subquery, 
ek)))
                                        return NULL;
-                               append(exps, e);
+                       } else {
+                               for ( ; n; n = n->next) {
+                                       sql_exp *e = rel_value_exp(query, NULL, 
n->data.sym, sql_sel, iek);
+
+                                       if (!e)
+                                               return NULL;
+                                       append(exps, e);
+                               }
+                               sq = rel_project(sql->sa, NULL, exps);
                        }
-                       sq = rel_project(sql->sa, NULL, exps);
                }
                if (!sq)
                        return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no 
such loader function '%s'", fname);
diff --git a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err 
b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
--- a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
+++ b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
@@ -35,7 +35,7 @@ ERROR = !CREATE FUNCTION: external name 
 CODE  = 3F000
 MAPI  = (monetdb) /var/tmp/mtest-23748/.s.monetdb.37404
 QUERY = select * from x((select id from _tables), (select schema_id from 
_tables));
-ERROR = !SELECT: 'x' requires a single sub query
+ERROR = !SELECT: The input for the table returning function 'x' must be either 
a single sub query, or a list of values
 CODE  = 42000
 
 # 09:35:12 >  
diff --git 
a/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
 
b/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
--- 
a/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
+++ 
b/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
@@ -33,7 +33,7 @@ ERROR = !CREATE FUNCTION: external name 
 CODE  = 3F000
 MAPI  = (monetdb) /var/tmp/mtest-23419/.s.monetdb.31192
 QUERY = select * from x((select id from _tables), (select schema_id from 
_tables));
-ERROR = !SELECT: 'x' requires a single sub query
+ERROR = !SELECT: The input for the table returning function 'x' must be either 
a single sub query, or a list of values
 CODE  = 42000
 
 # 13:48:49 >  
diff --git 
a/sql/test/BugTracker-2017/Tests/udf_crash_subquery_scalar_paramters.Bug-6399.stable.err
 
b/sql/test/BugTracker-2017/Tests/udf_crash_subquery_scalar_paramters.Bug-6399.stable.err
--- 
a/sql/test/BugTracker-2017/Tests/udf_crash_subquery_scalar_paramters.Bug-6399.stable.err
+++ 
b/sql/test/BugTracker-2017/Tests/udf_crash_subquery_scalar_paramters.Bug-6399.stable.err
@@ -37,7 +37,7 @@ ERROR = !SELECT: The input for the table
 CODE  = 42000
 MAPI  = (monetdb) /var/tmp/mtest-41450/.s.monetdb.30991
 QUERY = select * from crash2(1, (select idx from data));
-ERROR = !SELECT: no such table returning function 'crash2'
+ERROR = !SELECT: The input for the table returning function 'crash2' must be 
either a single sub query, or a list of values
 CODE  = 42000
 MAPI  = (monetdb) /var/tmp/mtest-25976/.s.monetdb.36797
 QUERY = select * from crash3((select idx from data), 2, 3);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to