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

Reply via email to