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