Changeset: 9963cf288abe for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9963cf288abe Modified Files: sql/server/rel_dump.c sql/server/rel_select.c sql/test/BugTracker-2020/Tests/remote-table-like.Bug-6841.py Branch: default Log Message:
ifthenelse, coalesce, casewhen and nullif functions have unique bind requires. Handle them separately on remote plans diffs (217 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 @@ -1017,7 +1017,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re } if (!(f = sql_bind_func_(sql, "sys", fname, tl, F_FILT))) - return sql_error(sql, -1, SQLSTATE(42000) "Filter: missing function '%s'\n", fname); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Filter: missing function '%s'\n", fname); if (!execute_priv(sql, f->func)) return sql_error(sql, -1, SQLSTATE(42000) "Filter: no privilege to call filter function '%s'\n", fname); return exp_filter(sql->sa, lexps, rexps, f, anti); @@ -1049,7 +1049,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re } convertIdent(tname); if (!(tpe = sql_bind_subtype(sql->sa, tname, d, s))) - return sql_error(sql, -1, SQLSTATE(42000) "SQL type %s(%d, %d) not found\n", tname, d, s); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SQL type %s(%d, %d) not found\n", tname, d, s); skipWS(r, pos); *e = old; if (r[*pos] == '[') { /* convert */ @@ -1077,7 +1077,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re tname = b; convertIdent(tname); if (!(tpe = sql_bind_subtype(sql->sa, tname, 0, 0))) - return sql_error(sql, -1, SQLSTATE(42000) "SQL type %s not found\n", tname); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SQL type %s not found\n", tname); st = readString(r,pos); if (st && strcmp(st, "NULL") == 0) exp = exp_atom(sql->sa, atom_general(sql->sa, tpe, NULL)); @@ -1121,7 +1121,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re convertIdent(tname); s = mvc_bind_schema(sql, tname); if (tname && !s) - return sql_error(sql, -1, SQLSTATE(42000) "Schema %s not found\n", tname); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Schema %s not found\n", tname); if (grp) { if (exps && exps->h) { list *ops = sa_list(sql->sa); @@ -1132,7 +1132,7 @@ 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, -1, SQLSTATE(42000) "Aggregate '%s%s%s %d' not found\n", tname ? tname : "", tname ? "." : "", cname, list_length(exps)); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Aggregate '%s%s%s %d' not found\n", tname ? tname : "", tname ? "." : "", cname, list_length(exps)); 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)); exp = exp_aggr( sql->sa, exps, a, unique, no_nils, CARD_ATOM, 1); @@ -1140,63 +1140,73 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re set_zero_if_empty(exp); } else { int nops = list_length(exps); - list *ops = sa_list(sql->sa); - for( n = exps->h; n; n = n->next) - append(ops, exp_subtype(n->data)); + if (!strcmp(tname, "sys") && (!strcmp(cname, "ifthenelse") || !strcmp(cname, "casewhen") || !strcmp(cname, "coalesce") || !strcmp(cname, "nullif"))) { + /* these functions are bound on a different way */ + if ((f = sql_find_func(sql, NULL, cname, !strcmp(cname, "ifthenelse") ? 3 : 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); + 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); + } + } else { + list *ops = sa_list(sql->sa); + for( n = exps->h; n; n = n->next) + append(ops, exp_subtype(n->data)); - f = sql_bind_func_(sql, tname, cname, ops, F_FUNC); - if (!f) { - sql->session->status = 0; /* if the function was not found clean the error */ - sql->errstr[0] = '\0'; - f = sql_bind_func_(sql, tname, cname, ops, F_ANALYTIC); - } - if (!f && nops > 1) { /* window functions without frames get 2 extra arguments */ - sql->session->status = 0; /* if the function was not found clean the error */ - sql->errstr[0] = '\0'; - list_remove_node(ops, NULL, ops->t); - list_remove_node(ops, NULL, ops->t); - f = sql_bind_func_(sql, tname, cname, ops, F_ANALYTIC); - } - if (!f && nops > 4) { /* window functions with frames get 5 extra arguments */ - sql->session->status = 0; /* if the function was not found clean the error */ - sql->errstr[0] = '\0'; - for (int i = 0 ; i < 3 ; i++) + f = sql_bind_func_(sql, tname, cname, ops, F_FUNC); + if (!f) { + sql->session->status = 0; /* if the function was not found clean the error */ + sql->errstr[0] = '\0'; + f = sql_bind_func_(sql, tname, cname, ops, F_ANALYTIC); + } + if (!f && nops > 1) { /* window functions without frames get 2 extra arguments */ + sql->session->status = 0; /* if the function was not found clean the error */ + sql->errstr[0] = '\0'; + list_remove_node(ops, NULL, ops->t); list_remove_node(ops, NULL, ops->t); - f = sql_bind_func_(sql, tname, cname, ops, F_ANALYTIC); - } + f = sql_bind_func_(sql, tname, cname, ops, F_ANALYTIC); + } + if (!f && nops > 4) { /* window functions with frames get 5 extra arguments */ + sql->session->status = 0; /* if the function was not found clean the error */ + sql->errstr[0] = '\0'; + for (int i = 0 ; i < 3 ; i++) + list_remove_node(ops, NULL, ops->t); + f = sql_bind_func_(sql, tname, cname, ops, F_ANALYTIC); + } + + 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); + /* fix scale of mul function, other type casts are explicit */ + if (f && f->func->fix_scale == SCALE_MUL && list_length(exps) == 2) { + sql_arg *ares = f->func->res->h->data; - 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); - /* fix scale of mul function, other type casts are explicit */ - if (f && f->func->fix_scale == SCALE_MUL && list_length(exps) == 2) { - sql_arg *ares = f->func->res->h->data; + if (strcmp(f->func->imp, "*") == 0 && ares->type.type->scale == SCALE_FIX) { + sql_subtype *res = f->res->h->data; + sql_subtype *lt = ops->h->data; + sql_subtype *rt = ops->h->next->data; - if (strcmp(f->func->imp, "*") == 0 && ares->type.type->scale == SCALE_FIX) { + res->digits = lt->digits; + res->scale = lt->scale + rt->scale; + } + } + /* fix scale of div function */ + if (f && f->func->fix_scale == SCALE_DIV && list_length(exps) == 2) { + sql_arg *ares = f->func->res->h->data; + + if (strcmp(f->func->imp, "/") == 0 && ares->type.type->scale == SCALE_FIX) { sql_subtype *res = f->res->h->data; - sql_subtype *lt = ops->h->data; - sql_subtype *rt = ops->h->next->data; + sql_subtype *lt = ops->h->data; + sql_subtype *rt = ops->h->next->data; - res->digits = lt->digits; - res->scale = lt->scale + rt->scale; + res->scale = lt->scale - rt->scale; + } } } - /* fix scale of div function */ - if (f && f->func->fix_scale == SCALE_DIV && list_length(exps) == 2) { - sql_arg *ares = f->func->res->h->data; - - if (strcmp(f->func->imp, "/") == 0 && ares->type.type->scale == SCALE_FIX) { - sql_subtype *res = f->res->h->data; - sql_subtype *lt = ops->h->data; - sql_subtype *rt = ops->h->next->data; - - res->scale = lt->scale - rt->scale; - } - } - if (f) exp = exp_op(sql->sa, list_empty(exps) ? NULL : exps, f); else - return sql_error(sql, -1, SQLSTATE(42000) "Function '%s%s%s %d' not found\n", tname ? tname : "", tname ? "." : "", cname, nops); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "Function '%s%s%s %d' not found\n", tname ? tname : "", tname ? "." : "", cname, nops); } } @@ -1635,7 +1645,7 @@ rel_read(mvc *sql, char *r, int *pos, li sql_column *c = mvc_bind_column(sql, t, cname); if (!c) - return sql_error(sql, -1, SQLSTATE(42S22) "UPDATE: no such column '%s.%s'\n", t->base.name, cname); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "UPDATE: no such column '%s.%s'\n", t->base.name, cname); if (!(e = update_check_column(sql, t, c, e, rrel, c->base.name, "UPDATE"))) return NULL; } @@ -1781,9 +1791,9 @@ rel_read(mvc *sql, char *r, int *pos, li (*pos)++; skipWS(r, pos); if (!(s = mvc_bind_schema(sql, sname))) - return sql_error(sql, -1, SQLSTATE(3F000) "No such schema '%s'\n", sname); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "No such schema '%s'\n", sname); if (!(t = mvc_bind_table(sql, s, tname))) - return sql_error(sql, -1, SQLSTATE(42S02) "Table missing '%s.%s'\n", sname, tname); + return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S02) "Table missing '%s.%s'\n", sname, tname); if (isMergeTable(t)) return sql_error(sql, -1, SQLSTATE(42000) "Merge tables not supported under remote connections\n"); if (isRemote(t)) 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 @@ -3837,8 +3837,7 @@ rel_case(sql_query *query, sql_rel **rel append(args, result); } assert(res); - if (res) - list_append(args, res); + list_append(args, res); list *types = sa_list(sql->sa); if (!opt_cond_exp) types = append(sa_list(sql->sa), condtype); 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 @@ -67,7 +67,10 @@ with tempfile.TemporaryDirectory() as fa node2_cur.execute("select count(*) over (), max(name) over (), min(name) over (partition by name order by name rows between 3 preceding and 2 preceding) from remote_data") if node2_cur.fetchall() != [(1, 'Name 1', None)]: sys.stderr.write("Just row (1, 'Name 1', None) expected") - + node2_cur.execute("""select case when id = 1 then 2 when id = 2 then 10 when id = 3 then 3 else 100 end, nullif(id, id), coalesce(id, id + 10, 10), + 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") # cleanup: shutdown the monetdb servers and remove tempdir node1_proc.communicate() node2_proc.communicate() _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list