Changeset: 461c8f779f19 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/461c8f779f19
Modified Files:
        sql/backends/monet5/UDF/pyapi3/Tests/pyloader3_01.test
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_cat.c
        sql/backends/monet5/sql_gencode.c
        sql/backends/monet5/sql_gencode.h
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
        sql/backends/monet5/sql_upgrades.c
        sql/backends/monet5/sql_user.c
        sql/common/sql_types.c
        sql/common/sql_types.h
        sql/include/sql_catalog.h
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_optimizer.c
        sql/server/rel_psm.c
        sql/server/sql_env.c
        sql/server/sql_qc.c
        sql/storage/store.c
        sql/test/miscellaneous/Tests/select_groupby.stable.err
Branch: sqlfuncfix
Log Message:

Started function backend gencode cleanup. SQL and MAL functions require 
instantiation before they can be used. Make sure a function is instantiated 
before using the obtained MAL module and function names


diffs (truncated from 930 to 300 lines):

diff --git a/sql/backends/monet5/UDF/pyapi3/Tests/pyloader3_01.test 
b/sql/backends/monet5/UDF/pyapi3/Tests/pyloader3_01.test
--- a/sql/backends/monet5/UDF/pyapi3/Tests/pyloader3_01.test
+++ b/sql/backends/monet5/UDF/pyapi3/Tests/pyloader3_01.test
@@ -29,7 +29,7 @@ SELECT name,func,mod,language,type,side_
 ----
 myfunc
 {@@_emit.emit({'a':42,'d':1})@}@;
-pyapi
+pyapi3
 6
 7
 True
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1241,7 +1241,13 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                list *l = sa_list(sql->sa), *exps = e->l;
                sql_subfunc *f = e->f;
                stmt *rows = NULL;
-               int push_cands = can_push_cands(sel, f);
+               const char *mod, *fimp;
+
+               /* attempt to instantiate nosql functions now, so we can know 
if we can push candidate lists */
+               if (f->func->lang == FUNC_LANG_MAL && 
backend_create_mal_func(be->mvc, f->func) < 0)
+                       return NULL;
+               mod = sql_func_mod(f->func);
+               fimp = sql_func_imp(f->func);
 
                if (f->func->side_effect && left && left->nrcols > 0) {
                        sql_subfunc *f1 = NULL;
@@ -1258,17 +1264,19 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                        sql->errstr[0] = '\0';
                }
                assert(!e->r);
-               if (strcmp(sql_func_mod(f->func), "") == 0 && 
strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, "star") == 
0)
-                       return left->op4.lval->h->data;
-               else if (!list_empty(exps)) {
+               if (strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
+                       if (strcmp(f->func->base.name, "star") == 0)
+                               return left->op4.lval->h->data;
+                       if (strcmp(f->func->base.name, "case") == 0)
+                               return exp2bin_case(be, e, left, right, sel, 
depth);
+                       if (strcmp(f->func->base.name, "casewhen") == 0)
+                               return exp2bin_casewhen(be, e, left, right, 
sel, depth);
+                       if (strcmp(f->func->base.name, "coalesce") == 0)
+                               return exp2bin_coalesce(be, e, left, right, 
sel, depth);
+               }
+               if (!list_empty(exps)) {
                        unsigned nrcols = 0;
-
-                       if (strcmp(sql_func_mod(f->func), "") == 0 && 
strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, "case") == 
0)
-                               return exp2bin_case(be, e, left, right, sel, 
depth);
-                       if (strcmp(sql_func_mod(f->func), "") == 0 && 
strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, 
"casewhen") == 0)
-                               return exp2bin_casewhen(be, e, left, right, 
sel, depth);
-                       if (strcmp(sql_func_mod(f->func), "") == 0 && 
strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, 
"coalesce") == 0)
-                               return exp2bin_coalesce(be, e, left, right, 
sel, depth);
+                       int push_cands = can_push_cands(sel, mod, fimp);
 
                        assert(list_length(exps) == list_length(f->func->ops) 
|| f->func->type == F_ANALYTIC || f->func->type == F_LOADER || f->func->vararg 
|| f->func->varres);
                        for (en = exps->h; en; en = en->next) {
@@ -2119,12 +2127,12 @@ rel2bin_table(backend *be, sql_rel *rel,
                                                else
                                                        getArg(q, 0) = 
newTmpVariable(be->mb, type);
                                        }
+                                       if (backend_create_func(be, f->func, 
NULL, ops) < 0)
+                                               return NULL;
                                        str mod = sql_func_mod(f->func);
                                        str fcn = sql_func_imp(f->func);
                                        q = pushStr(be->mb, q, mod);
                                        q = pushStr(be->mb, q, fcn);
-                                       if (backend_create_func(be, f->func, 
NULL, ops) < 0)
-                                               return NULL;
                                        psub = stmt_direct_func(be, q);
 
                                        if (ids) /* push input rowids column */
diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -957,7 +957,6 @@ create_func(mvc *sql, char *sname, char 
        sql_func *nf;
        sql_subfunc *sf;
        sql_schema *s = NULL;
-       int clientid = sql->clientid;
        char *F = NULL, *fn = NULL, *base = replace ? "CREATE OR REPLACE" : 
"CREATE";
 
        FUNC_TYPE_STR(f->type, F, fn)
@@ -967,8 +966,6 @@ create_func(mvc *sql, char *sname, char 
                throw(SQL,"sql.create_func", SQLSTATE(3F000) "%s %s: no such 
schema '%s'", base, F, sname);
        if (!mvc_schema_privs(sql, s))
                throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s: access 
denied for %s to schema '%s'", base, F, get_string_global_var(sql, 
"current_user"), s->base.name);
-       if (strlen(fname) >= IDLENGTH)
-               throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s: name '%s' 
too large for the backend", base, F, fname);
 
        if (replace) {
                list *tl = sa_list(sql->sa);
@@ -982,24 +979,14 @@ create_func(mvc *sql, char *sname, char 
 
                if ((sf = sql_bind_func_(sql, s->base.name, fname, tl, 
f->type)) != NULL) {
                        sql_func *sff = sf->func;
-                       bool backend_ok = true;
                        char *fimp = NULL;
 
                        if (!sff->s || sff->system)
                                throw(SQL,"sql.create_func", SQLSTATE(42000) 
"%s %s: not allowed to replace system %s %s;", base, F, fn, sff->base.name);
 
-                       if (sff->lang == FUNC_LANG_MAL && 
mal_function_find_implementation_address(&fimp, sql, sff) < 0) {
-                               backend_ok = false;
-                               sql->session->status = 0; /* clean the error */
-                               sql->errstr[0] = '\0';
-                       }
-
                        /* if all function parameters are the same, return */
-                       if (backend_ok && sff->lang == f->lang && sff->type == 
f->type &&
+                       if (sff->lang == f->lang && sff->type == f->type &&
                                sff->varres == f->varres && sff->vararg == 
f->vararg &&
-                               strcmp(sff->s->base.name, s->base.name) == 0 &&
-                               ((!sff->mod && !f->mod) || (sff->mod && f->mod 
&& strcmp(sff->mod, f->mod) == 0)) &&
-                               (sff->lang != FUNC_LANG_MAL || strcmp(fimp, 
f->imp) == 0) &&
                                ((!sff->query && !f->query) || (sff->query && 
f->query && strcmp(sff->query, f->query) == 0)) &&
                                list_cmp(sff->res, f->res, (fcmp) &args_cmp) == 
0 &&
                                list_cmp(sff->ops, f->ops, (fcmp) &args_cmp) == 
0) {
@@ -1035,18 +1022,24 @@ create_func(mvc *sql, char *sname, char 
                        break;
        }
        switch (nf->lang) {
-       case FUNC_LANG_INT:
-       case FUNC_LANG_MAL: /* shouldn't be reachable, but leave it here */
-               if (!backend_resolve_function(&clientid, nf))
-                       throw(SQL,"sql.create_func", SQLSTATE(3F000) "%s %s: 
external name %s.%s not bound", base, F, nf->mod, nf->base.name);
-               if (nf->query == NULL)
-                       break;
+       case FUNC_LANG_MAL:
+               /* instantiate MAL functions while being created */
+               if (backend_create_mal_func(sql, nf) < 0) {
+                       if (strlen(sql->errstr) > 6 && sql->errstr[5] == '!')
+                               throw(SQL, "sql.create_func", "%s", 
sql->errstr);
+                       else
+                               throw(SQL, "sql.create_func", SQLSTATE(42000) 
"%s", sql->errstr);
+               }
                /* fall through */
        case FUNC_LANG_SQL: {
                char *buf;
                sql_rel *r = NULL;
                sql_allocator *sa = sql->sa;
 
+               /* for sql functions, this check is necessary here */
+               if (nf->lang == FUNC_LANG_SQL && strlen(fname) >= IDLENGTH)
+                       throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s: 
name '%s' too large for the backend", base, F, fname);
+
                assert(nf->query);
                if (!(sql->sa = sa_create(sql->pa))) {
                        sql->sa = sa;
diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -954,7 +954,7 @@ monet5_resolve_function(ptr M, sql_func 
        Client c;
        Module m;
        int clientID = *(int*) M;
-       const char *mname = putName(f->mod), *fname = putName(f->imp);
+       const char *mname = putName(sql_func_mod(f)), *fname = 
putName(sql_func_imp(f));
 
        if (!mname || !fname)
                return 0;
@@ -1016,95 +1016,9 @@ monet5_resolve_function(ptr M, sql_func 
        return 0;
 }
 
-static int
-backend_create_r_func(backend *be, sql_func *f)
-{
-       (void)be;
-       _DELETE(f->mod);
-       _DELETE(f->imp);
-       f->mod = GDKstrdup("rapi");
-       switch(f->type) {
-       case  F_AGGR:
-               f->imp = GDKstrdup("eval_aggr");
-               break;
-       case  F_PROC: /* no output */
-       case  F_FUNC:
-       default: /* ie also F_FILT and F_UNION for now */
-               f->imp = GDKstrdup("eval");
-               break;
-       }
-       return 0;
-}
-
-/* Create the MAL block for a registered function and optimize it */
-static int
-backend_create_py_func(backend *be, sql_func *f)
-{
-       (void)be;
-       _DELETE(f->mod);
-       _DELETE(f->imp);
-       f->mod = GDKstrdup("pyapi3");
-       switch(f->type) {
-       case  F_AGGR:
-               f->imp = GDKstrdup("eval_aggr");
-               break;
-       case F_LOADER:
-               f->imp = GDKstrdup("eval_loader");
-               break;
-       case  F_PROC: /* no output */
-       case  F_FUNC:
-       default: /* ie also F_FILT and F_UNION for now */
-               f->imp = GDKstrdup("eval");
-               break;
-       }
-       return 0;
-}
-
+/* Parse the SQL query from the function, and extract the MAL function from 
the generated abstract syntax tree */
 static int
-backend_create_map_py_func(backend *be, sql_func *f)
-{
-       (void)be;
-       _DELETE(f->mod);
-       _DELETE(f->imp);
-       f->mod = GDKstrdup("pyapi3map");
-       switch(f->type) {
-       case  F_AGGR:
-               f->imp = GDKstrdup("eval_aggr");
-               break;
-       case  F_PROC: /* no output */
-       case  F_FUNC:
-       default: /* ie also F_FILT and F_UNION for now */
-               f->imp = GDKstrdup("eval");
-               break;
-       }
-       return 0;
-}
-
-/* Create the MAL block for a registered function and optimize it */
-static int
-backend_create_c_func(backend *be, sql_func *f)
-{
-       (void)be;
-       _DELETE(f->mod);
-       _DELETE(f->imp);
-       f->mod = GDKstrdup("capi");
-       switch(f->type) {
-       case  F_AGGR:
-               f->imp = GDKstrdup("eval_aggr");
-               break;
-       case F_LOADER:
-       case F_PROC: /* no output */
-       case F_FUNC:
-       default: /* ie also F_FILT and F_UNION for now */
-               f->imp = GDKstrdup("eval");
-               break;
-       }
-       return 0;
-}
-
-/* Parse the SQL query from the function, and extract the MAL function from 
the generated abstract syntax tree */
-int
-mal_function_find_implementation_address(str *res, mvc *m, sql_func *f)
+mal_function_find_implementation_address(mvc *m, sql_func *f)
 {
        mvc o = *m;
        buffer *b = NULL;
@@ -1152,7 +1066,12 @@ mal_function_find_implementation_address
        } else {
                l = m->sym->data.lval;
                ext_name = l->h->next->next->next->data.lval;
-               if (!(*res = _STRDUP(qname_schema_object(ext_name)))) /* found 
the implementation, set it */
+               const char *imp = qname_schema_object(ext_name);
+
+               assert(!f->imp);
+               if (strlen(imp) >= IDLENGTH)
+                       (void) sql_error(m, 02, SQLSTATE(42000) "MAL function 
name '%s' too large for the backend", imp);
+               else if (!(f->imp = _STRDUP(imp))) /* found the implementation, 
set it */
                        (void) sql_error(m, 02, SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
        }
 
@@ -1179,6 +1098,27 @@ mal_function_find_implementation_address
        return m->errstr[0] == '\0' ? 0 : -1; /* m was set back to o */
 }
 
+int
+backend_create_mal_func(mvc *m, sql_func *f)
+{
+       if (!f->instantiated) {
+               if (strlen(f->mod) >= IDLENGTH) {
+                       (void) sql_error(m, 01, SQLSTATE(42000) "MAL module 
name '%s' too large for the backend", f->mod);
+                       return -1;
+               }
+               if (mal_function_find_implementation_address(m, f) < 0)
+                       return -1;
+               if (!backend_resolve_function(&(m->clientid), f)) {
+                       (void) sql_error(m, 02, SQLSTATE(3F000) "MAL external 
name %s.%s not bound (%s.%s)", f->mod, f->imp, f->s->base.name, f->base.name);
+                       _DELETE(f->imp);
+                       f->imp = NULL;
+                       return -1;
+               }
+               f->instantiated = TRUE;
+       }
+       return 0;
+}
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to