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