Changeset: 2d76ae286a7c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2d76ae286a7c
Added Files:
        sql/test/BugTracker-2022/Tests/python-udf-inside-udf.Bug-7252.test
Modified Files:
        monetdb5/extras/rapi/rapi.c
        sql/backends/monet5/UDF/capi/capi.c
        sql/backends/monet5/UDF/pyapi3/pyapi3.c
        sql/backends/monet5/UDF/pyapi3/pyloader3.c
        sql/backends/monet5/sql_statement.c
        sql/test/BugTracker-2022/Tests/All
        sql/test/BugTracker-2022/Tests/SingleServer
Branch: Jan2022
Log Message:

Fix for bug #7252 Don't use resolved function parameter in the backend, because 
it is scoped to the current session only.
Use the function itself instead.
However improvement has to be done for loader functions, because they use 
information from the resolved function. It should be done differently


diffs (180 lines):

diff --git a/monetdb5/extras/rapi/rapi.c b/monetdb5/extras/rapi/rapi.c
--- a/monetdb5/extras/rapi/rapi.c
+++ b/monetdb5/extras/rapi/rapi.c
@@ -642,13 +642,7 @@ static str RAPIeval(Client cntxt, MalBlk
                          "Embedded R initialization has failed");
        }
 
-       if (!grouped) {
-               sql_subfunc *sqlmorefun = (*(sql_subfunc**) 
getArgReference(stk, pci, pci->retc+has_card_arg));
-               if (sqlmorefun) sqlfun = sqlmorefun->func;
-       } else {
-               sqlfun = *(sql_func**) getArgReference(stk, pci, 
pci->retc+has_card_arg);
-       }
-
+       sqlfun = *(sql_func**) getArgReference(stk, pci, 
pci->retc+has_card_arg);
        args = (str*) GDKzalloc(sizeof(str) * pci->argc);
        if (args == NULL) {
                throw(MAL, "rapi.eval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
diff --git a/sql/backends/monet5/UDF/capi/capi.c 
b/sql/backends/monet5/UDF/capi/capi.c
--- a/sql/backends/monet5/UDF/capi/capi.c
+++ b/sql/backends/monet5/UDF/capi/capi.c
@@ -529,16 +529,7 @@ static str CUDFeval(Client cntxt, MalBlk
                sa = (struct sigaction) {.sa_flags = 0,};
        }
 
-       if (!grouped) {
-               sql_subfunc *sqlmorefun =
-                       (*(sql_subfunc **)getArgReference_ptr(stk, pci, 
pci->retc));
-               if (sqlmorefun)
-                       sqlfun =
-                               (*(sql_subfunc **)getArgReference_ptr(stk, pci, 
pci->retc))->func;
-       } else {
-               sqlfun = *(sql_func **)getArgReference_ptr(stk, pci, pci->retc);
-       }
-
+       sqlfun = *(sql_func **)getArgReference_ptr(stk, pci, pci->retc);
        funcname = sqlfun ? sqlfun->base.name : "yet_another_c_function";
 
        args = (str *)GDKzalloc(sizeof(str) * pci->argc);
diff --git a/sql/backends/monet5/UDF/pyapi3/pyapi3.c 
b/sql/backends/monet5/UDF/pyapi3/pyapi3.c
--- a/sql/backends/monet5/UDF/pyapi3/pyapi3.c
+++ b/sql/backends/monet5/UDF/pyapi3/pyapi3.c
@@ -213,15 +213,7 @@ static str PyAPIeval(Client cntxt, MalBl
                card = 1;
        }
 
-       if (!grouped) {
-               sql_subfunc *sqlmorefun =
-                       (*(sql_subfunc **)getArgReference(stk, pci, pci->retc + 
has_card_arg));
-               if (sqlmorefun) {
-                       sqlfun = sqlmorefun->func;
-               }
-       } else {
-               sqlfun = *(sql_func **)getArgReference(stk, pci, pci->retc + 
has_card_arg);
-       }
+       sqlfun = *(sql_func **)getArgReference(stk, pci, pci->retc + 
has_card_arg);
        exprStr = *getArgReference_str(stk, pci, pci->retc + 1 + has_card_arg);
        varres = sqlfun ? sqlfun->varres : 0;
        retcols = !varres ? pci->retc : -1;
diff --git a/sql/backends/monet5/UDF/pyapi3/pyloader3.c 
b/sql/backends/monet5/UDF/pyapi3/pyloader3.c
--- a/sql/backends/monet5/UDF/pyapi3/pyloader3.c
+++ b/sql/backends/monet5/UDF/pyapi3/pyloader3.c
@@ -68,13 +68,13 @@ PYAPI3PyAPIevalLoader(Client cntxt, MalB
 
        char *loader_additional_args[] = {"_emit", "_conn"};
 
-    if (!PYAPI3PyAPIInitialized()) {
-        throw(MAL, "pyapi3.eval",
-              SQLSTATE(PY000) "Embedded Python is enabled but an error was 
thrown during initialization.");
-    }
-    sqlmorefun = *(sql_subfunc**) getArgReference(stk, pci, pci->retc);
-    sqlfun = sqlmorefun->func;
-    exprStr = *getArgReference_str(stk, pci, pci->retc + 1);
+       if (!PYAPI3PyAPIInitialized()) {
+               throw(MAL, "pyapi3.eval",
+                               SQLSTATE(PY000) "Embedded Python is enabled but 
an error was thrown during initialization.");
+       }
+       sqlmorefun = *(sql_subfunc**) getArgReference(stk, pci, pci->retc);
+       sqlfun = sqlmorefun->func;
+       exprStr = *getArgReference_str(stk, pci, pci->retc + 1);
 
        args = (str *)GDKzalloc(pci->argc * sizeof(str));
        if (!args) {
diff --git a/sql/backends/monet5/sql_statement.c 
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -1381,7 +1381,7 @@ stmt_genselect(backend *be, stmt *lops, 
                // push pointer to the SQL structure into the MAL call
                // allows getting argument names for example
                if (LANG_EXT(f->func->lang))
-                       q = pushPtr(mb, q, f); // nothing to see here, please 
move along
+                       q = pushPtr(mb, q, f->func); // nothing to see here, 
please move along
                // f->query contains the R code to be run
                if (f->func->lang == FUNC_LANG_R || f->func->lang >= 
FUNC_LANG_PY)
                        q = pushStr(mb, q, f->func->query);
@@ -3460,8 +3460,15 @@ stmt_Nop(backend *be, stmt *ops, stmt *s
                                setVarType(mb, getArg(q, 0), 
res->type->localtype);
                        }
                }
-               if (LANG_EXT(f->func->lang))
-                       q = pushPtr(mb, q, f);
+               if (LANG_EXT(f->func->lang)) {
+                       /* TODO LOADER functions still use information in 
sql_subfunc struct
+                          that won't be visible to other sessions if another 
function uses them.
+                          It has to be cleaned up */
+                       if (f->func->type == F_LOADER)
+                               q = pushPtr(mb, q, f);
+                       else
+                               q = pushPtr(mb, q, f->func);
+               }
                if (f->func->lang == FUNC_LANG_C) {
                        q = pushBit(mb, q, 0);
                } else if (f->func->lang == FUNC_LANG_CPP) {
diff --git a/sql/test/BugTracker-2022/Tests/All 
b/sql/test/BugTracker-2022/Tests/All
--- a/sql/test/BugTracker-2022/Tests/All
+++ b/sql/test/BugTracker-2022/Tests/All
@@ -2,3 +2,4 @@ transaction-conflict.Bug-7228
 insert-not-null.Bug-7232
 !ARCH_BITS32?index-function-query.Bug-7238
 recreate-view.Bug-7241
+HAVE_LIBPY3?python-udf-inside-udf.Bug-7252
diff --git a/sql/test/BugTracker-2022/Tests/SingleServer 
b/sql/test/BugTracker-2022/Tests/SingleServer
--- a/sql/test/BugTracker-2022/Tests/SingleServer
+++ b/sql/test/BugTracker-2022/Tests/SingleServer
@@ -0,0 +1,1 @@
+--set embedded_py=3
diff --git a/sql/test/BugTracker-2022/Tests/python-udf-inside-udf.Bug-7252.test 
b/sql/test/BugTracker-2022/Tests/python-udf-inside-udf.Bug-7252.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2022/Tests/python-udf-inside-udf.Bug-7252.test
@@ -0,0 +1,49 @@
+@connection(id=1, username=monetdb, password=monetdb)
+statement ok
+START TRANSACTION
+
+@connection(id=1)
+statement ok
+CREATE FUNCTION pyfunc(i integer) returns table (pyi integer)
+language P
+{
+       x = range(1, i + 1)
+       return([x])
+}
+
+@connection(id=1)
+statement ok
+CREATE FUNCTION ups(i integer) returns table (i integer)
+BEGIN
+       RETURN SELECT pyi FROM pyfunc(i);
+END
+
+@connection(id=1)
+statement ok
+COMMIT
+
+@connection(id=1)
+query I nosort
+select i from ups(1)
+----
+1
+
+@connection(id=2, username=monetdb, password=monetdb)
+query I nosort
+select i from ups(1)
+----
+1
+
+@connection(id=3, username=monetdb, password=monetdb)
+query I nosort
+select i from ups(1)
+----
+1
+
+@connection(id=2)
+statement ok
+DROP FUNCTION ups
+
+@connection(id=2)
+statement ok
+DROP FUNCTION pyfunc
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to