Changeset: ce029816bd34 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ce029816bd34
Modified Files:
        sql/server/rel_select.c
        sql/test/Users/Tests/userCallFunction.SQL.py
        sql/test/analytics/Tests/analytics02.stable.err
        sql/test/analytics/Tests/analytics14.stable.err
        sql/test/analytics/Tests/analytics14.stable.out
        sql/test/subquery/Tests/subquery4.stable.err
        sql/test/subquery/Tests/subquery4.stable.out
Branch: Oct2020
Log Message:

Give a better error message when a user doesn't have execute privilege to a 
function. This fixes bug #7077


diffs (truncated from 853 to 300 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
@@ -350,7 +350,7 @@ query_exp_optname(sql_query *query, sql_
 }
 
 static sql_subfunc *
-bind_func_(mvc *sql, sql_schema *s, char *fname, list *ops, sql_ftype type)
+bind_func_(mvc *sql, sql_schema *s, char *fname, list *ops, sql_ftype type, 
bool *found)
 {
        sql_subfunc *sf = NULL;
 
@@ -359,13 +359,15 @@ bind_func_(mvc *sql, sql_schema *s, char
            execute_priv(sql, sql->forward) && type == sql->forward->type)
                return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
        sf = sql_bind_func_(sql->sa, s, fname, ops, type);
+       if (found)
+               *found |= sf != NULL;
        if (sf && execute_priv(sql, sf->func))
                return sf;
        return NULL;
 }
 
 static sql_subfunc *
-bind_func(mvc *sql, sql_schema *s, char *fname, sql_subtype *t1, sql_subtype 
*t2, sql_ftype type)
+bind_func(mvc *sql, sql_schema *s, char *fname, sql_subtype *t1, sql_subtype 
*t2, sql_ftype type, bool *found)
 {
        sql_subfunc *sf = NULL;
 
@@ -383,13 +385,15 @@ bind_func(mvc *sql, sql_schema *s, char 
                }
        }
        sf = sql_bind_func(sql->sa, s, fname, t1, t2, type);
+       if (found)
+               *found |= sf != NULL;
        if (sf && execute_priv(sql, sf->func))
                return sf;
        return NULL;
 }
 
 static sql_subfunc *
-bind_member_func(mvc *sql, sql_schema *s, char *fname, sql_subtype *t, int 
nrargs, sql_ftype type, sql_subfunc *prev)
+bind_member_func(mvc *sql, sql_schema *s, char *fname, sql_subtype *t, int 
nrargs, sql_ftype type, sql_subfunc *prev, bool *found)
 {
        sql_subfunc *sf = NULL;
 
@@ -397,19 +401,23 @@ bind_member_func(mvc *sql, sql_schema *s
                is_subtype(t, &((sql_arg *) sql->forward->ops->h->data)->type) 
&& execute_priv(sql, sql->forward) && type == sql->forward->type)
                return sql_dup_subfunc(sql->sa, sql->forward, NULL, t);
        sf = sql_bind_member(sql->sa, s, fname, t, type, nrargs, prev);
+       if (found)
+               *found |= sf != NULL;
        if (sf && execute_priv(sql, sf->func))
                return sf;
        return NULL;
 }
 
 static sql_subfunc *
-find_func(mvc *sql, sql_schema *s, char *fname, int len, sql_ftype type, 
sql_subfunc *prev )
+find_func(mvc *sql, sql_schema *s, char *fname, int len, sql_ftype type, 
sql_subfunc *prev, bool *found)
 {
        sql_subfunc *sf = NULL;
 
        if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 && 
list_length(sql->forward->ops) == len && execute_priv(sql, sql->forward) && 
type == sql->forward->type)
                return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
        sf = sql_find_func(sql->sa, s, fname, len, type, prev);
+       if (found)
+               *found |= sf != NULL;
        if (sf && execute_priv(sql, sf->func))
                return sf;
        return NULL;
@@ -492,13 +500,15 @@ check_arguments_and_find_largest_any_typ
 sql_exp *
 find_table_function(mvc *sql, sql_schema *s, char *fname, list *exps, list 
*tl, sql_ftype type)
 {
-       sql_subfunc *f = bind_func_(sql, s, fname, tl, type);
+       bool found = false;
+       sql_subfunc *f = bind_func_(sql, s, fname, tl, type, &found);
 
        assert(type == F_UNION || type == F_LOADER);
        if (!f && list_length(tl)) {
                int len, match = 0;
                list *funcs = sql_find_funcs(sql->sa, s, fname, 
list_length(tl), type);
 
+               found |= !list_empty(funcs);
                for (node *n = funcs->h; n ; ) { /* Reduce on privileges */
                        sql_subfunc *sf = n->data;
                        node *nn = n->next;
@@ -530,7 +540,8 @@ find_table_function(mvc *sql, sql_schema
                        return NULL;
                return exp_op(sql->sa, exps, f);
        }
-       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no such %s function 
'%s'", type == F_UNION ? "table returning" : "loader", fname);
+       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: %s %s function 
'%s'", found ? "insufficient privileges for" : "no such",
+                                        type == F_UNION ? "table returning" : 
"loader", fname);
 }
 
 static sql_rel *
@@ -651,15 +662,17 @@ rel_named_table_function(sql_query *quer
 static sql_exp *
 rel_op_(mvc *sql, sql_schema *s, char *fname, exp_kind ek)
 {
+       bool found = false;
        sql_subfunc *f = NULL;
        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, s, fname, NULL, type)) && check_card(ek.card, 
f)) {
-               return exp_op(sql->sa, NULL, f);
-       } else {
-               return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no such 
operator '%s'", fname);
-       }
+       if ((f = bind_func_(sql, s, fname, NULL, type, &found))) {
+               if (check_card(ek.card, f))
+                       return exp_op(sql->sa, NULL, f);
+               found = false;
+       }
+       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: %s operator '%s'", 
found ? "insufficient privileges for" : "no such", fname);
 }
 
 static sql_exp*
@@ -1447,6 +1460,7 @@ rel_filter(mvc *sql, sql_rel *rel, list 
        sql_subfunc *f = NULL;
        sql_schema *s = cur_schema(sql);
        list *tl = sa_list(sql->sa);
+       bool found = false;
 
        for (n = l->h; n; n = n->next){
                sql_exp *e = n->data;
@@ -1461,8 +1475,8 @@ rel_filter(mvc *sql, sql_rel *rel, list 
        if (sname && !(s = mvc_bind_schema(sql, sname)))
                return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: no such 
schema '%s'", sname);
        /* find filter function */
-       if (!(f = bind_func_(sql, s, filter_op, tl, F_FILT)))
-               f = find_func(sql, s, filter_op, list_length(tl), F_FILT, NULL);
+       if (!(f = bind_func_(sql, s, filter_op, tl, F_FILT, &found)))
+               f = find_func(sql, s, filter_op, list_length(tl), F_FILT, NULL, 
&found);
        if (f) {
                node *n,*m = f->func->ops->h;
                list *nexps = sa_list(sql->sa);
@@ -1490,7 +1504,7 @@ rel_filter(mvc *sql, sql_rel *rel, list 
                r = nexps;
        }
        if (!f)
-               return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no such 
FILTER function '%s'", filter_op);
+               return sql_error(sql, 02, SQLSTATE(42000) "SELECT: %s FILTER 
function '%s'", found ? "insufficient privileges for" : "no such", filter_op);
        e = exp_filter(sql->sa, l, r, f, anti);
 
        if (exps_one_is_rel(l) || exps_one_is_rel(r)) /* uncorrelated subquery 
case */
@@ -1727,12 +1741,14 @@ static sql_exp*
        int table_func = (ek.card == card_relation);
        sql_ftype type = (ek.card == card_loader)?F_LOADER:((ek.card == 
card_none)?F_PROC:
                   ((ek.card == card_relation)?F_UNION:F_FUNC));
-
-       f = bind_func_(sql, s, fname, tl, type);
+       bool found = false;
+
+       f = bind_func_(sql, s, fname, tl, type, &found);
        if (!f && list_length(tl)) {
                int len, match = 0;
                list *funcs = sql_find_funcs(sql->sa, s, fname, 
list_length(tl), type);
 
+               found |= !list_empty(funcs);
                for (node *n = funcs->h; n ; ) { /* Reduce on privileges */
                        sql_subfunc *sf = n->data;
                        node *nn = n->next;
@@ -1764,7 +1780,7 @@ static sql_exp*
                        return NULL;
                return exp_op(sql->sa, exps, f);
        }
-       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no such operator 
'%s'", fname);
+       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: %s operator '%s'", 
found ? "insufficient privileges for" : "no such", fname);
 }
 
 static sql_exp *
@@ -2693,7 +2709,7 @@ rel_op(sql_query *query, sql_rel **rel, 
        if (sname && !(s = mvc_bind_schema(sql, sname)))
                return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: no such 
schema '%s'", sname);
 
-       sf = find_func(sql, s, fname, 0, F_AGGR, NULL);
+       sf = find_func(sql, s, fname, 0, F_AGGR, NULL, NULL);
        if (sf)
                return _rel_aggr(query, rel, 0, s, fname, NULL, f);
        return rel_op_(sql, s, fname, ek);
@@ -2702,6 +2718,7 @@ rel_op(sql_query *query, sql_rel **rel, 
 sql_exp *
 rel_unop_(mvc *sql, sql_rel *rel, sql_exp *e, sql_schema *s, char *fname, int 
card)
 {
+       bool found = false;
        sql_subfunc *f = NULL;
        sql_subtype *t = exp_subtype(e);
        sql_ftype type = (card == card_loader)?F_LOADER:((card == 
card_none)?F_PROC:
@@ -2712,9 +2729,9 @@ rel_unop_(mvc *sql, sql_rel *rel, sql_ex
 
        /* handle param's early */
        if (!t) {
-               f = find_func(sql, s, fname, 1, type, NULL);
+               f = find_func(sql, s, fname, 1, type, NULL, &found);
                if (!f)
-                       f = find_func(sql, s, fname, 1, F_AGGR, NULL);
+                       f = find_func(sql, s, fname, 1, F_AGGR, NULL, &found);
                if (f) {
                        sql_arg *a = f->func->ops->h->data;
 
@@ -2723,9 +2740,9 @@ rel_unop_(mvc *sql, sql_rel *rel, sql_ex
                                return NULL;
                }
         } else {
-               f = bind_func(sql, s, fname, t, NULL, type);
+               f = bind_func(sql, s, fname, t, NULL, type, &found);
                if (!f)
-                       f = bind_func(sql, s, fname, t, NULL, F_AGGR);
+                       f = bind_func(sql, s, fname, t, NULL, F_AGGR, &found);
        }
 
        if (f && type_has_tz(t) && f->func->fix_scale == SCALE_FIX) {
@@ -2743,9 +2760,13 @@ rel_unop_(mvc *sql, sql_rel *rel, sql_ex
         * the value to the type needed by this function!
         */
        if (!f) {
-               while ((f = find_func(sql, s, fname, 1, type, f)) != NULL && 
check_card(card, f)) {
+               while ((f = find_func(sql, s, fname, 1, type, f, &found)) != 
NULL) {
                        sql_exp *oe = e;
 
+                       if (!check_card(card, f)) {
+                               found = false; /* reset found */
+                               break;
+                       }
                        if (!f->func->vararg) {
                                sql_arg *a = f->func->ops->h->data;
 
@@ -2758,30 +2779,27 @@ rel_unop_(mvc *sql, sql_rel *rel, sql_ex
                        /* reset error */
                        sql->session->status = 0;
                        sql->errstr[0] = '\0';
-               }
-       }
-       if (f && check_card(card, f)) {
-               if (f->func->fix_scale == INOUT) {
-                       sql_subtype *res = f->res->h->data;
-                       res->digits = t->digits;
-                       res->scale = t->scale;
+                       found = false;
                }
-               if (card == card_relation && e->card > CARD_ATOM) {
-                       sql_subfunc *zero_or_one = sql_bind_func(sql->sa, 
sql->session->schema, "zero_or_one", exp_subtype(e), NULL, F_AGGR);
-
-                       e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, 
has_nil(e));
+       }
+       if (f) {
+               if (check_card(card, f)) {
+                       if (f->func->fix_scale == INOUT) {
+                               sql_subtype *res = f->res->h->data;
+                               res->digits = t->digits;
+                               res->scale = t->scale;
+                       }
+                       if (card == card_relation && e->card > CARD_ATOM) {
+                               sql_subfunc *zero_or_one = 
sql_bind_func(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(e), 
NULL, F_AGGR);
+
+                               e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, 
CARD_ATOM, has_nil(e));
+                       }
+                       return exp_unop(sql->sa, e, f);
                }
-               return exp_unop(sql->sa, e, f);
-       } else if (e) {
-               if (t) {
-                       char *type = t->type->sqlname;
-
-                       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no 
such unary operator '%s(%s)'", fname, type);
-               } else {
-                       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no 
such unary operator '%s(?)'", fname);
-               }
-       }
-       return NULL;
+               found = false; /* reset found */
+       }
+       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: %s unary operator 
'%s(%s)'",
+                                        found ? "insufficient privileges for" 
: "no such", fname, t ? t->type->sqlname : "?");
 }
 
 static sql_exp *
@@ -2799,7 +2817,7 @@ rel_unop(sql_query *query, sql_rel **rel
        if (sname && !(s = mvc_bind_schema(sql, sname)))
                return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: no such 
schema '%s'", sname);
 
-       sf = find_func(sql, s, fname, 1, F_AGGR, NULL);
+       sf = find_func(sql, s, fname, 1, F_AGGR, NULL, NULL);
        if (sf)
                return rel_aggr(query, rel, se, f);
 
@@ -2823,6 +2841,8 @@ rel_binop_(mvc *sql, sql_rel *rel, sql_e
        sql_subtype *t1 = exp_subtype(l), *t2 = exp_subtype(r);
        sql_subfunc *f = NULL;
        sql_ftype type = (card == card_loader)?F_LOADER:((card == 
card_none)?F_PROC:((card == card_relation)?F_UNION:F_FUNC));
+       bool found = false;
+
        if (card == card_loader)
                card = card_none;
 
@@ -2832,6 +2852,7 @@ rel_binop_(mvc *sql, sql_rel *rel, sql_e
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to