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]