Changeset: c357386bee28 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c357386bee28
Modified Files:
sql/common/sql_types.c
sql/common/sql_types.h
sql/server/rel_psm.c
sql/server/rel_select.c
sql/server/sql_mvc.h
Branch: Oct2014
Log Message:
handle (again) recursive function definitions
diffs (truncated from 329 to 300 lines):
diff --git a/sql/common/sql_types.c b/sql/common/sql_types.c
--- a/sql/common/sql_types.c
+++ b/sql/common/sql_types.c
@@ -381,7 +381,7 @@ subfunc_cmp( sql_subfunc *f1, sql_subfun
return -1;
}
-static int
+int
arg_subtype_cmp(sql_arg *a, sql_subtype *t)
{
if (a->type.type->eclass == EC_ANY)
@@ -545,8 +545,8 @@ is_sqlfunc(sql_func *f)
return f->sql;
}
-static sql_subfunc*
-_dup_subfunc(sql_allocator *sa, sql_func *f, list *ops, sql_subtype *member)
+sql_subfunc*
+sql_dup_subfunc(sql_allocator *sa, sql_func *f, list *ops, sql_subtype *member)
{
node *tn;
unsigned int scale = 0, digits = 0;
@@ -613,9 +613,9 @@ func_cmp(sql_allocator *sa, sql_func *f,
{
if (strcmp(f->base.name, name) == 0) {
if (f->vararg)
- return _dup_subfunc(sa, f, NULL, NULL);
+ return sql_dup_subfunc(sa, f, NULL, NULL);
if (nrargs < 0 || list_length(f->ops) == nrargs)
- return _dup_subfunc(sa, f, NULL, NULL);
+ return sql_dup_subfunc(sa, f, NULL, NULL);
}
return NULL;
}
@@ -693,7 +693,7 @@ sql_bind_member(sql_allocator *sa, sql_s
continue;
if (strcmp(f->base.name, sqlfname) == 0) {
if (list_length(f->ops) == nrargs && is_subtype(tp,
&((sql_arg *) f->ops->h->data)->type))
- return _dup_subfunc(sa, f, NULL, tp);
+ return sql_dup_subfunc(sa, f, NULL, tp);
}
}
if (tp && tp->type->eclass == EC_NUM) {
@@ -706,7 +706,7 @@ sql_bind_member(sql_allocator *sa, sql_s
if (strcmp(f->base.name, sqlfname) == 0 &&
list_length(f->ops) == nrargs) {
if (((sql_arg *)
f->ops->h->data)->type.type->eclass == EC_DEC &&
((sql_arg *)
f->ops->h->data)->type.type->localtype == tp->type->localtype)
- return _dup_subfunc(sa, f, NULL, tp);
+ return sql_dup_subfunc(sa, f, NULL, tp);
}
}
}
@@ -720,7 +720,7 @@ sql_bind_member(sql_allocator *sa, sql_s
continue;
if (strcmp(f->base.name, sqlfname) == 0) {
if (list_length(f->ops) == nrargs &&
is_subtype(tp, &((sql_arg *) f->ops->h->data)->type))
- return _dup_subfunc(sa, f, NULL, tp);
+ return sql_dup_subfunc(sa, f, NULL, tp);
}
}
}
@@ -772,7 +772,7 @@ sql_bind_func_(sql_allocator *sa, sql_sc
continue;
if (strcmp(f->base.name, sqlfname) == 0) {
if (list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) ==
0)
- return _dup_subfunc(sa, f, ops, NULL);
+ return sql_dup_subfunc(sa, f, ops, NULL);
}
}
if (s) {
@@ -785,7 +785,7 @@ sql_bind_func_(sql_allocator *sa, sql_sc
continue;
if (strcmp(f->base.name, sqlfname) == 0) {
if (list_cmp(f->ops, ops, (fcmp)
&arg_subtype_cmp) == 0)
- return _dup_subfunc(sa, f, ops, NULL);
+ return sql_dup_subfunc(sa, f, ops,
NULL);
}
}
}
@@ -839,7 +839,7 @@ sql_bind_func_result_(sql_allocator *sa,
continue;
firstres = f->res->h->data;
if (strcmp(f->base.name, sqlfname) == 0 &&
(is_subtype(&firstres->type, res) || firstres->type.type->eclass == EC_ANY) &&
list_cmp(f->ops, ops, (fcmp) &arg_subtype_cmp) == 0)
- return _dup_subfunc(sa, f, ops, NULL);
+ return sql_dup_subfunc(sa, f, ops, NULL);
}
return NULL;
}
diff --git a/sql/common/sql_types.h b/sql/common/sql_types.h
--- a/sql/common/sql_types.h
+++ b/sql/common/sql_types.h
@@ -83,6 +83,7 @@ extern char *sql_subtype_string(sql_subt
extern int type_cmp(sql_type *t1, sql_type *t2);
extern int subtype_cmp(sql_subtype *t1, sql_subtype *t2);
+extern int arg_subtype_cmp(sql_arg *a, sql_subtype *t);
extern int is_subtype(sql_subtype *t1, sql_subtype *t2);
extern char *subtype2string(sql_subtype *t);
@@ -118,6 +119,7 @@ extern sql_func *sql_create_func4(sql_al
extern sql_func *sql_create_func_(sql_allocator *sa, char *name, char *mod,
char *imp, list *ops, sql_arg *res, bit side_effect, int type, int fix_scale);
extern sql_func *sql_create_sqlfunc(sql_allocator *sa, char *name, char *imp,
list *ops, sql_arg *res);
+extern sql_subfunc* sql_dup_subfunc(sql_allocator *sa, sql_func *f, list *ops,
sql_subtype *member);
extern char *sql_func_imp(sql_func *f);
extern char *sql_func_mod(sql_func *f);
diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -791,8 +791,11 @@ rel_create_func(mvc *sql, dlist *qname,
list *b = NULL;
sql_schema *old_schema = cur_schema(sql);
+ if (create) /* needed for recursive functions */
+ sql->forward = f = mvc_create_func(sql,
sql->sa, s, fname, l, restype, type, lang, "user", q, q, FALSE, vararg);
sql->session->schema = s;
b = sequential_block(sql, (ra)?&ra->type:NULL,
ra?NULL:restype, body, NULL, is_func);
+ sql->forward = NULL;
sql->session->schema = old_schema;
sql->params = NULL;
if (!b)
@@ -811,8 +814,6 @@ rel_create_func(mvc *sql, dlist *qname,
/* in execute mode we instantiate the function
*/
if (instantiate || deps) {
return rel_psm_block(sql->sa, b);
- } else if (create) {
- f = mvc_create_func(sql, sql->sa, s,
fname, l, restype, type, lang, "user", q, q, FALSE, vararg);
}
} else {
char *fmod = qname_module(ext_name);
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
@@ -1422,6 +1422,49 @@ rel_bind_column2( mvc *sql, sql_rel *rel
return NULL;
}
+static sql_subfunc *
+bind_func_(mvc *sql, sql_schema *s, char *fname, list *ops, int type )
+{
+ if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 &&
+ list_cmp(sql->forward->ops, ops, (fcmp)&arg_subtype_cmp) == 0)
+ return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
+ return sql_bind_func_(sql->sa, s, fname, ops, type);
+}
+
+static sql_subfunc *
+bind_func(mvc *sql, sql_schema *s, char *fname, sql_subtype *t1, sql_subtype
*t2, int type )
+{
+ assert(t1);
+ if (sql->forward) {
+ if (strcmp(fname, sql->forward->base.name) == 0 &&
+ ((!t1 && list_length(sql->forward->ops) == 0) ||
+ (!t2 && list_length(sql->forward->ops) == 1 &&
subtype_cmp(sql->forward->ops->h->data, t1) == 0) ||
+ (list_length(sql->forward->ops) == 2 &&
+ subtype_cmp(sql->forward->ops->h->data, t1) == 0 &&
+ subtype_cmp(sql->forward->ops->h->next->data, t2) ==
0))) {
+ return sql_dup_subfunc(sql->sa, sql->forward, NULL,
NULL);
+ }
+ }
+ return sql_bind_func(sql->sa, s, fname, t1, t2, type);
+}
+
+static sql_subfunc *
+bind_member_func(mvc *sql, sql_schema *s, char *fname, sql_subtype *t, int
nrargs)
+{
+ if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 &&
+ list_length(sql->forward->ops) == nrargs && is_subtype(t,
&((sql_arg *) sql->forward->ops->h->data)->type))
+ return sql_dup_subfunc(sql->sa, sql->forward, NULL, t);
+ return sql_bind_member(sql->sa, s, fname, t, nrargs);
+}
+
+static sql_subfunc *
+find_func(mvc *sql, sql_schema *s, char *fname, int len, int type )
+{
+ if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 &&
list_length(sql->forward->ops) == len)
+ return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
+ return sql_find_func(sql->sa, s, fname, len, type);
+}
+
static sql_rel *
rel_named_table_function(mvc *sql, sql_rel *rel, symbol *query)
{
@@ -1490,12 +1533,12 @@ rel_named_table_function(mvc *sql, sql_r
if (sname)
s = mvc_bind_schema(sql, sname);
- sf = sql_bind_func_(sql->sa, s, fname, tl, F_UNION);
+ sf = bind_func_(sql, s, fname, tl, F_UNION);
if (sf) {
e = exp_op(sql->sa, exps, sf);
} else if (list_length(tl) &&
- ((sf = sql_bind_member(sql->sa, s, fname,
tl->h->data, list_length(tl))) != NULL ||
- (sf = sql_find_func(sql->sa, s, fname,
list_length(tl), F_UNION)) != NULL)){
+ ((sf = bind_member_func(sql, s, fname, tl->h->data,
list_length(tl))) != NULL ||
+ (sf = find_func(sql, s, fname, list_length(tl),
F_UNION)) != NULL)){
node *n, *m;
list *nexps;
@@ -3404,12 +3447,12 @@ rel_unop_(mvc *sql, sql_exp *e, sql_sche
if (!s)
s = sql->session->schema;
t = exp_subtype(e);
- f = sql_bind_func(sql->sa, s, fname, t, NULL, type);
+ f = bind_func(sql, s, fname, t, NULL, type);
/* try to find the function without a type, and convert
* the value to the type needed by this function!
*/
if (!f &&
- (f = sql_find_func(sql->sa, s, fname, 1, type)) != NULL &&
+ (f = find_func(sql, s, fname, 1, type)) != NULL &&
((card == card_none && !f->res) ||
(card != card_none && f->res))) {
@@ -3472,9 +3515,9 @@ rel_unop(mvc *sql, sql_rel **rel, symbol
if (!s)
s = sql->session->schema;
t = exp_subtype(e);
- f = sql_bind_func(sql->sa, s, fname, t, NULL, type);
+ f = bind_func(sql, s, fname, t, NULL, type);
if (!f)
- f = sql_bind_func(sql->sa, s, fname, t, NULL, F_AGGR);
+ f = bind_func(sql, s, fname, t, NULL, F_AGGR);
if (f && IS_AGGR(f->func))
return _rel_aggr(sql, rel, 0, s, fname, l->next, fs);
@@ -3537,9 +3580,9 @@ rel_binop_(mvc *sql, sql_exp *l, sql_exp
t2 = exp_subtype(r);
}
- f = sql_bind_func(sql->sa, s, fname, t1, t2, type);
+ f = bind_func(sql, s, fname, t1, t2, type);
if (!f && is_commutative(fname)) {
- f = sql_bind_func(sql->sa, s, fname, t2, t1, type);
+ f = bind_func(sql, s, fname, t2, t1, type);
if (f) {
sql_subtype *tmp = t1;
t1 = t2;
@@ -3586,7 +3629,7 @@ rel_binop_(mvc *sql, sql_exp *l, sql_exp
sql_exp *or = r;
if (!EC_NUMBER(t1->type->eclass) &&
- (f = sql_bind_member(sql->sa, s, fname, t1, 2)) != NULL &&
+ (f = bind_member_func(sql, s, fname, t1, 2)) != NULL &&
((card == card_none && !f->res) ||
(card != card_none && f->res))) {
/* try finding function based on first argument */
@@ -3610,7 +3653,7 @@ rel_binop_(mvc *sql, sql_exp *l, sql_exp
/* try operators */
t1 = exp_subtype(l);
t2 = exp_subtype(r);
- f = sql_bind_func(sql->sa, s, fname, t1, t2, type);
+ f = bind_func(sql, s, fname, t1, t2, type);
if (f &&
((card == card_none && !f->res) ||
(card != card_none && f->res))) {
@@ -3644,7 +3687,7 @@ rel_binop_(mvc *sql, sql_exp *l, sql_exp
t1 = exp_subtype(l);
(void) exp_subtype(r);
- if ((f = sql_bind_member(sql->sa, s, fname, t1, 2)) != NULL &&
+ if ((f = bind_member_func(sql, s, fname, t1, 2)) != NULL &&
((card == card_none && !f->res) ||
(card != card_none && f->res))) {
/* try finding function based on first argument */
@@ -3664,7 +3707,7 @@ rel_binop_(mvc *sql, sql_exp *l, sql_exp
l = ol;
r = or;
/* everything failed, fall back to bind on function name only */
- if ((f = sql_find_func(sql->sa, s, fname, 2, type)) != NULL &&
+ if ((f = find_func(sql, s, fname, 2, type)) != NULL &&
((card == card_none && !f->res) ||
(card != card_none && f->res))) {
@@ -3716,7 +3759,7 @@ rel_binop(mvc *sql, sql_rel **rel, symbo
s = mvc_bind_schema(sql, sname);
if (type == F_FUNC) {
- sql_subfunc *func = sql_find_func(sql->sa, s, fname, 2, F_AGGR);
+ sql_subfunc *func = find_func(sql, s, fname, 2, F_AGGR);
if (func) {
if (!l || !r) { /* reset error */
sql->session->status = 0;
@@ -3748,7 +3791,7 @@ rel_nop_(mvc *sql, sql_exp *a1, sql_exp
if (!s)
s = sql->session->schema;
- f = sql_bind_func_(sql->sa, s, fname, tl, type);
+ f = bind_func_(sql, s, fname, tl, type);
if (!f)
return sql_error(sql, 02, "SELECT: no such operator '%s'",
fname);
if (!a4)
@@ -3788,11 +3831,11 @@ rel_nop(mvc *sql, sql_rel **rel, symbol
}
if (sname)
s = mvc_bind_schema(sql, sname);
- f = sql_bind_func_(sql->sa, s, fname, tl, type);
+ f = bind_func_(sql, s, fname, tl, type);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list