Changeset: bb9bb6e31b70 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bb9bb6e31b70
Modified Files:
        sql/server/rel_select.c
Branch: default
Log Message:

For n-ary and table functions, check for type compatibility before privileges. 
Also attempt for every function found. Small fixes


diffs (223 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
@@ -524,55 +524,53 @@ sql_exp *
 find_table_function(mvc *sql, char *sname, char *fname, list *exps, list *tl, 
sql_ftype type)
 {
        bool found = false;
-       sql_subfunc *f = NULL;
+       list *ff = NULL;
+       sql_subfunc *f = NULL, **ffuncs;
+       int i = 0, *scores, nfunc;
 
        assert(type == F_UNION || type == F_LOADER);
-       if (!(f = bind_func_(sql, sname, fname, tl, type, false, &found)) && 
list_length(tl)) {
-               int len, match = 0;
-               list *ff;
-
-               sql->session->status = 0; /* if the function was not found 
clean the error */
-               sql->errstr[0] = '\0';
-               if (!(ff = sql_find_funcs(sql, sname, fname, list_length(tl), 
type, false))) {
-                       char *arg_list = list_length(tl) ? 
nary_function_arg_types_2str(sql, tl, list_length(tl)) : NULL;
-                       return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) 
"SELECT: %s %s function %s%s%s'%s'(%s)",
-                                                        found ? "insufficient 
privileges for" : "no such", type == F_UNION ? "table returning" : "loader", 
sname ? "'":"", sname ? sname : "",
-                                                        sname ? "'.":"", 
fname, arg_list ? arg_list : "");
-               }
-               if (!list_empty(ff)) {
-                       found = true;
-                       for (node *n = ff->h; n ; ) { /* Reduce on privileges */
-                               sql_subfunc *sf = n->data;
-                               node *nn = n->next;
-
-                               if (!execute_priv(sql, sf->func))
-                                       list_remove_node(ff, NULL, n);
-                               n = nn;
-                       }
-               }
-               len = list_length(ff);
-               if (len > 1) {
-                       int i, score = 0;
-                       node *n;
-
-                       for (i = 0, n = ff->h; i<len; i++, n = n->next) {
-                               int cscore = score_func(n->data, tl);
-                               if (cscore > score) {
-                                       score = cscore;
-                                       match = i;
-                               }
-                       }
-               }
-               if (!list_empty(ff))
-                       f = list_fetch(ff, match);
-       }
-       if (f) {
-               if (f->func->vararg)
-                       return exp_op(sql->sa, exps, f);
-               if (!list_empty(exps) && !(exps = 
check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1)))
-                       return NULL;
+       if ((f = bind_func_(sql, sname, fname, tl, type, false, &found))) {
+               list *nexps = exps;
+               if (list_empty(tl) || f->func->vararg || (nexps = 
check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1)))
+                       return exp_op(sql->sa, nexps, f);
+               found = false;
+       }
+       sql->session->status = 0; /* reset error */
+       sql->errstr[0] = '\0';
+       if (list_empty(tl) || !(ff = sql_find_funcs(sql, sname, fname, 
list_length(tl), type, false)) || list_empty(ff)) {
+               char *arg_list = list_length(tl) ? 
nary_function_arg_types_2str(sql, tl, list_length(tl)) : NULL;
+               return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s 
%s function %s%s%s'%s'(%s)",
+                                                found ? "insufficient 
privileges for" : "no such", type == F_UNION ? "table returning" : "loader", 
sname ? "'":"", sname ? sname : "",
+                                                sname ? "'.":"", fname, 
arg_list ? arg_list : "");
+       }
+
+       /* sort functions by their score */
+       nfunc = list_length(ff);
+       scores = SA_NEW_ARRAY(sql->ta, int, nfunc);
+       ffuncs = SA_NEW_ARRAY(sql->ta, sql_subfunc*, nfunc);
+       for (node *n = ff->h; n; i++, n = n->next) {
+               ffuncs[i] = n->data;
+               scores[i] = score_func(n->data, tl);
+       }
+       GDKqsort(scores, ffuncs, NULL, nfunc, sizeof(int), sizeof(void *), 
TYPE_int, true, true);
+
+       for (int i = 0 ; i < nfunc && !f; i++) {
+               list *nexps = exps;
+               sql_subfunc *nf = ffuncs[i];
+
+               if (!list_empty(tl) && !nf->func->vararg && !(nexps = 
check_arguments_and_find_largest_any_type(sql, NULL, exps, nf, 1))) {
+                       /* reset error */
+                       sql->session->status = 0;
+                       sql->errstr[0] = '\0';
+               } else if (!execute_priv(sql, nf->func)) {
+                       found = true; /* something was found */
+               } else {
+                       f = nf;
+                       exps = nexps;
+               }
+       }
+       if (f)
                return exp_op(sql->sa, exps, f);
-       }
        char *arg_list = list_length(tl) ? nary_function_arg_types_2str(sql, 
tl, list_length(tl)) : NULL;
        return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s %s 
function %s%s%s'%s'(%s)",
                                         found ? "insufficient privileges for" 
: "no such", type == F_UNION ? "table returning" : "loader", sname ? "'":"", 
sname ? sname : "",
@@ -1787,57 +1785,55 @@ static sql_exp*
 _rel_nop(mvc *sql, char *sname, char *fname, list *tl, sql_rel *rel, list 
*exps, exp_kind ek)
 {
        bool found = false;
-       sql_subfunc *f = NULL;
-       int table_func = (ek.card == card_relation);
+       list *ff = NULL;
+       sql_subfunc *f = NULL, **ffuncs;
+       int table_func = (ek.card == card_relation), i = 0, *scores, nfunc;
        sql_ftype type = (ek.card == card_loader)?F_LOADER:((ek.card == 
card_none)?F_PROC:
                   ((ek.card == card_relation)?F_UNION:F_FUNC));
 
-       if (!(f = bind_func_(sql, sname, fname, tl, type, false, &found)) && 
list_length(tl)) {
-               int len, match = 0;
-               list *ff;
-
-               sql->session->status = 0; /* if the function was not found 
clean the error */
-               sql->errstr[0] = '\0';
-               if (!(ff = sql_find_funcs(sql, sname, fname, list_length(tl), 
type, false))) {
-                       char *arg_list = list_length(tl) ? 
nary_function_arg_types_2str(sql, tl, list_length(tl)) : NULL;
-                       return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) 
"SELECT: %s operator %s%s%s'%s'(%s)",
-                                                        found ? "insufficient 
privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? 
"'.":"", fname, arg_list ? arg_list : "");
-               }
-               if (!list_empty(ff)) {
-                       found = true;
-                       for (node *n = ff->h; n ; ) { /* Reduce on privileges */
-                               sql_subfunc *sf = n->data;
-                               node *nn = n->next;
-
-                               if (!execute_priv(sql, sf->func))
-                                       list_remove_node(ff, NULL, n);
-                               n = nn;
-                       }
-               }
-               len = list_length(ff);
-               if (len > 1) {
-                       int i, score = 0;
-                       node *n;
-
-                       for (i = 0, n = ff->h; i<len; i++, n = n->next) {
-                               int cscore = score_func(n->data, tl);
-                               if (cscore > score) {
-                                       score = cscore;
-                                       match = i;
-                               }
-                       }
-               }
-               if (!list_empty(ff))
-                       f = list_fetch(ff, match);
-       }
-       if (f) {
-               if (f->func->vararg)
-                       return exp_op(sql->sa, exps, f);
-               if (!(exps = check_arguments_and_find_largest_any_type(sql, 
rel, exps, f, table_func)))
-                       return NULL;
+       assert(list_length(tl));
+       if ((f = bind_func_(sql, sname, fname, tl, type, false, &found))) {
+               list *nexps = exps;
+               if (f->func->vararg || (nexps = 
check_arguments_and_find_largest_any_type(sql, rel, exps, f, table_func)))
+                       return exp_op(sql->sa, nexps, f);
+               found = false;
+       }
+       sql->session->status = 0; /* reset error */
+       sql->errstr[0] = '\0';
+       if (!(ff = sql_find_funcs(sql, sname, fname, list_length(tl), type, 
false)) || list_empty(ff)) {
+               char *arg_list = list_length(tl) ? 
nary_function_arg_types_2str(sql, tl, list_length(tl)) : NULL;
+               return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s 
operator %s%s%s'%s'(%s)",
+                                                found ? "insufficient 
privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? 
"'.":"", fname, arg_list ? arg_list : "");
+       }
+
+       /* sort functions by their score */
+       nfunc = list_length(ff);
+       scores = SA_NEW_ARRAY(sql->ta, int, nfunc);
+       ffuncs = SA_NEW_ARRAY(sql->ta, sql_subfunc*, nfunc);
+       for (node *n = ff->h; n; i++, n = n->next) {
+               ffuncs[i] = n->data;
+               scores[i] = score_func(n->data, tl);
+       }
+       GDKqsort(scores, ffuncs, NULL, nfunc, sizeof(int), sizeof(void *), 
TYPE_int, true, true);
+
+       for (int i = 0 ; i < nfunc && !f; i++) {
+               list *nexps = exps;
+               sql_subfunc *nf = ffuncs[i];
+
+               if (!nf->func->vararg && !(nexps = 
check_arguments_and_find_largest_any_type(sql, rel, exps, nf, table_func))) {
+                       /* reset error */
+                       sql->session->status = 0;
+                       sql->errstr[0] = '\0';
+               } else if (!execute_priv(sql, nf->func)) {
+                       found = true; /* something was found */
+               } else {
+                       f = nf;
+                       exps = nexps;
+               }
+       }
+       if (f)
                return exp_op(sql->sa, exps, f);
-       }
-       char *arg_list = list_length(tl) ? nary_function_arg_types_2str(sql, 
tl, list_length(tl)) : NULL;
+       char *arg_list = nary_function_arg_types_2str(sql, tl, list_length(tl));
        return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s 
operator %s%s%s'%s'(%s)",
                                         found ? "insufficient privileges for" 
: "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname, 
arg_list ? arg_list : "");
 }
@@ -3822,7 +3818,7 @@ static sql_exp *
                        a = sql_bind_func_(sql, sname, aname, 
exp_types(sql->sa, nexps), F_AGGR, false);
 
                        if (a) {
-                               if (!list_empty(exps) && !(nexps = 
check_arguments_and_find_largest_any_type(sql, *rel, exps, a, 0))) {
+                               if (!(nexps = 
check_arguments_and_find_largest_any_type(sql, *rel, exps, a, 0))) {
                                        a = NULL;
                                        /* reset error */
                                        sql->session->status = 0;
@@ -5026,6 +5022,7 @@ rel_rankop(sql_query *query, sql_rel **r
                                sql->session->status = 0; /* reset error */
                                sql->errstr[0] = '\0';
                                found = false; /* reset found */
+                               wf = NULL;
                        }
                } else {
                        sql->session->status = 0; /* if the function was not 
found clean the error */
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to