Changeset: 642ba632a207 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/642ba632a207 Modified Files: sql/server/rel_dump.c sql/server/rel_exp.c sql/server/rel_exp.h sql/server/rel_select.c sql/server/rel_select.h sql/test/BugTracker-2020/Tests/remote-table-like.Bug-6841.py Branch: default Log Message:
I moved the check arguments function into the wrong translation unit. Also added more debugging information for functions not found on remote plans diffs (266 lines): diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c --- a/sql/server/rel_dump.c +++ b/sql/server/rel_dump.c @@ -974,6 +974,31 @@ parse_atom(mvc *sql, char *r, int *pos, } static sql_exp* +function_error_string(mvc *sql, const char *schema, const char *fname, list *exps, bool found, sql_ftype type) +{ + char *arg_list = NULL, *F = NULL, *fn = NULL; + + FUNC_TYPE_STR(type, F, fn) + + (void) F; + if (!list_empty(exps)) { + for (node *n = exps->h; n ; n = n->next) { + sql_subtype *t = exp_subtype(n->data); + char *tpe = t ? sql_subtype_string(sql->ta, t) : "?"; + + if (arg_list) { + arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe); + } else { + arg_list = tpe; + } + } + } + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s %s %s%s%s'%s'(%s)", + found ? "Insufficient privileges for" : "No such", fn, schema ? "'":"", schema ? schema : "", + schema ? "'.":"", fname, arg_list ? arg_list : ""); +} + +static sql_exp* exp_read(mvc *sql, sql_rel *lrel, sql_rel *rrel, list *top_exps, char *r, int *pos, int grp, int in_cmp) { int f = -1, old, d=0, s=0, unique = 0, no_nils = 0, quote = 0, zero_if_empty = 0, sem = 0, anti = 0; @@ -1189,9 +1214,9 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re a = sql_bind_func(sql, tname, cname, sql_bind_localtype("void"), NULL, F_AGGR); /* count(*) */ } if (!a) - return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Aggregate '%s%s%s %d' not found\n", tname ? tname : "", tname ? "." : "", cname, list_length(exps)); + return function_error_string(sql, tname, cname, exps, false, F_AGGR); if (!execute_priv(sql, a->func)) - return sql_error(sql, -1, SQLSTATE(42000) "Aggregate: no privilege to call aggregate '%s%s%s %d'\n", tname ? tname : "", tname ? "." : "", cname, list_length(exps)); + return function_error_string(sql, tname, cname, exps, true, F_AGGR); exp = exp_aggr( sql->sa, exps, a, unique, no_nils, CARD_ATOM, 1); if (zero_if_empty) set_zero_if_empty(exp); @@ -1201,7 +1226,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re /* these functions are bound on a different way */ if ((f = sql_find_func(sql, NULL, cname, 2, F_FUNC, NULL))) { if (!execute_priv(sql, f->func)) - return sql_error(sql, -1, SQLSTATE(42000) "Function: no privilege to call function '%s%s%s %d'\n", tname ? tname : "", tname ? "." : "", cname, nops); + return function_error_string(sql, tname, cname, exps, true, F_FUNC); sql_exp *res = exps->t->data; sql_subtype *restype = exp_subtype(res); f->res->h->data = sql_create_subtype(sql->sa, restype->type, restype->digits, restype->scale); @@ -1233,7 +1258,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re } if (f && !execute_priv(sql, f->func)) - return sql_error(sql, -1, SQLSTATE(42000) "Function: no privilege to call function '%s%s%s %d'\n", tname ? tname : "", tname ? "." : "", cname, nops); + return function_error_string(sql, tname, cname, exps, true, F_FUNC); /* apply scale fixes if needed */ if (f && f->func->type != F_ANALYTIC) { if (list_length(exps) == 1) { @@ -1313,7 +1338,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re } } } else { - return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Function '%s%s%s %d' not found\n", tname ? tname : "", tname ? "." : "", cname, nops); + return function_error_string(sql, tname, cname, exps, false, F_FUNC); } } } diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c --- a/sql/server/rel_exp.c +++ b/sql/server/rel_exp.c @@ -2956,73 +2956,6 @@ exp_sum_scales(sql_subfunc *f, sql_exp * } } -list * -check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, sql_subfunc *sf, int maybe_zero_or_one) -{ - list *nexps = new_exp_list(sql->sa); - sql_subtype *atp = NULL, super, *res = !list_empty(sf->res) ? sf->res->h->data: NULL; - unsigned int rdigits = 0; /* used for res of type char and varchar */ - - /* find largest any type argument */ - for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) { - sql_arg *a = m->data; - sql_exp *e = n->data; - sql_subtype *t = exp_subtype(e); - - if (a->type.type->eclass == EC_ANY) { - if (t && atp) { - result_datatype(&super, t, atp); - atp = &super; - } else if (t) { - atp = t; - } - } - } - if (atp && atp->type->localtype == TYPE_void) /* NULL */ - atp = sql_bind_localtype("str"); - for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) { - sql_arg *a = m->data; - sql_exp *e = n->data; - sql_subtype *ntp = &a->type, *t = exp_subtype(e); - - if (a->type.type->eclass == EC_ANY && atp) - ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale); - else if (t && ntp->digits == 0 && (!strcmp(a->type.type->base.name, "char") || !strcmp(a->type.type->base.name, "varchar"))) - ntp = sql_create_subtype(sql->sa, a->type.type, type_digits_to_char_digits(t), 0); - if (!(e = exp_check_type(sql, ntp, rel, e, type_equal))) - return NULL; - if (maybe_zero_or_one && e->card > CARD_ATOM) { - sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "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)); - } - append(nexps, e); - - /* for (var)char returning functions the output type will be the biggest string found except for fix_scale cases */ - if (res && res->digits == 0 && (t = exp_subtype(e)) && (!strcmp(res->type->base.name, "char") || !strcmp(res->type->base.name, "varchar"))) { - unsigned int tdigits = type_digits_to_char_digits(t); - if (sf->func->fix_scale == DIGITS_ADD) { - unsigned int nvalue = rdigits + tdigits; - if (nvalue < rdigits || nvalue >= (unsigned int) INT32_MAX) - return sql_error(sql, 02, SQLSTATE(42000) "SELECT: output number of digits for %s is too large", sf->func->base.name); - rdigits = nvalue; - } else if (sf->func->fix_scale == INOUT) { - if (n == exps->h) - rdigits = tdigits; - } else { - rdigits = sql_max(rdigits, tdigits); - } - } - } - /* dirty hack */ - if (sf->func->type != F_PROC && sf->func->type != F_UNION && sf->func->type != F_LOADER && res) { - if (res->type->eclass == EC_ANY && atp) - sf->res->h->data = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale); - else if (res->digits == 0 && (!strcmp(res->type->base.name, "char") || !strcmp(res->type->base.name, "varchar"))) - res->digits = rdigits; - } - return nexps; -} - int exp_aggr_is_count(sql_exp *e) { diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h --- a/sql/server/rel_exp.h +++ b/sql/server/rel_exp.h @@ -196,7 +196,6 @@ extern atom *exp_flatten(mvc *sql, sql_e extern sql_exp *exp_scale_algebra(mvc *sql, sql_subfunc *f, sql_rel *rel, sql_exp *l, sql_exp *r); extern void exp_sum_scales(sql_subfunc *f, sql_exp *l, sql_exp *r); -extern list *check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, sql_subfunc *sf, int maybe_zero_or_one); extern int exp_aggr_is_count(sql_exp *e); extern list *check_distinct_exp_names(mvc *sql, list *exps); 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 @@ -452,6 +452,73 @@ score_func( sql_subfunc *sf, list *tl) return score; } +list * +check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, sql_subfunc *sf, int maybe_zero_or_one) +{ + list *nexps = new_exp_list(sql->sa); + sql_subtype *atp = NULL, super, *res = !list_empty(sf->res) ? sf->res->h->data: NULL; + unsigned int rdigits = 0; /* used for res of type char and varchar */ + + /* find largest any type argument */ + for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) { + sql_arg *a = m->data; + sql_exp *e = n->data; + sql_subtype *t = exp_subtype(e); + + if (a->type.type->eclass == EC_ANY) { + if (t && atp) { + result_datatype(&super, t, atp); + atp = &super; + } else if (t) { + atp = t; + } + } + } + if (atp && atp->type->localtype == TYPE_void) /* NULL */ + atp = sql_bind_localtype("str"); + for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) { + sql_arg *a = m->data; + sql_exp *e = n->data; + sql_subtype *ntp = &a->type, *t = exp_subtype(e); + + if (a->type.type->eclass == EC_ANY && atp) + ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale); + else if (t && ntp->digits == 0 && (!strcmp(a->type.type->base.name, "char") || !strcmp(a->type.type->base.name, "varchar"))) + ntp = sql_create_subtype(sql->sa, a->type.type, type_digits_to_char_digits(t), 0); + if (!(e = exp_check_type(sql, ntp, rel, e, type_equal))) + return NULL; + if (maybe_zero_or_one && e->card > CARD_ATOM) { + sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "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)); + } + append(nexps, e); + + /* for (var)char returning functions the output type will be the biggest string found except for fix_scale cases */ + if (res && res->digits == 0 && (t = exp_subtype(e)) && (!strcmp(res->type->base.name, "char") || !strcmp(res->type->base.name, "varchar"))) { + unsigned int tdigits = type_digits_to_char_digits(t); + if (sf->func->fix_scale == DIGITS_ADD) { + unsigned int nvalue = rdigits + tdigits; + if (nvalue < rdigits || nvalue >= (unsigned int) INT32_MAX) + return sql_error(sql, 02, SQLSTATE(42000) "SELECT: output number of digits for %s is too large", sf->func->base.name); + rdigits = nvalue; + } else if (sf->func->fix_scale == INOUT) { + if (n == exps->h) + rdigits = tdigits; + } else { + rdigits = sql_max(rdigits, tdigits); + } + } + } + /* dirty hack */ + if (sf->func->type != F_PROC && sf->func->type != F_UNION && sf->func->type != F_LOADER && res) { + if (res->type->eclass == EC_ANY && atp) + sf->res->h->data = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale); + else if (res->digits == 0 && (!strcmp(res->type->base.name, "char") || !strcmp(res->type->base.name, "varchar"))) + res->digits = rdigits; + } + return nexps; +} + static char * nary_function_arg_types_2str(mvc *sql, list* types, int N) { diff --git a/sql/server/rel_select.h b/sql/server/rel_select.h --- a/sql/server/rel_select.h +++ b/sql/server/rel_select.h @@ -30,5 +30,6 @@ extern sql_rel *rel_with_query(sql_query extern sql_rel *table_ref(sql_query *query, sql_rel *rel, symbol *tableref, int lateral, list *refs); extern sql_exp *find_table_function(mvc *sql, char *sname, char *fname, list *exps, list *tl, sql_ftype type); extern sql_rel *rel_loader_function(sql_query* query, symbol* s, list *fexps, sql_subfunc **loader_function); +extern list *check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, sql_subfunc *sf, int maybe_zero_or_one); #endif /*_REL_SELECT_H_*/ diff --git a/sql/test/BugTracker-2020/Tests/remote-table-like.Bug-6841.py b/sql/test/BugTracker-2020/Tests/remote-table-like.Bug-6841.py --- a/sql/test/BugTracker-2020/Tests/remote-table-like.Bug-6841.py +++ b/sql/test/BugTracker-2020/Tests/remote-table-like.Bug-6841.py @@ -71,6 +71,13 @@ with tempfile.TemporaryDirectory() as fa case id when 1 then 5 when 2 then 10 when 3 then 60 else 4 end, greatest(id - 7, id + 7), lead(1,1,1) over () from remote_data""") if node2_cur.fetchall() != [(2, None, 1, 5, 8, 1)]: sys.stderr.write("Just row (2, None, 1, 5, 8, 1) expected") + node2_cur.execute("create function \"myfunc\"(\"myarg\" int) returns int return \"myarg\";") + try: + node2_cur.execute("select \"myfunc\"(1) from remote_data") + sys.stderr.write("Exception expected") + except pymonetdb.DatabaseError as e: + pass + # cleanup: shutdown the monetdb servers and remove tempdir node1_cur.close() node1_conn.close() _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list