Changeset: 8788a082bb23 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/8788a082bb23
Branch: Jul2021
Log Message:

merged


diffs (truncated from 312 to 300 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
@@ -543,6 +543,40 @@ static char *RAPIinstalladdons(void) {
        return NULL;
 }
 
+static str
+empty_return(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, size_t retcols, oid 
seqbase)
+{
+       for (size_t i = 0; i < retcols; i++) {
+               if (isaBatType(getArgType(mb, pci, i))) {
+                       BAT *b = COLnew(seqbase, getBatType(getArgType(mb, pci, 
i)), 0, TRANSIENT);
+                       if (!b) {
+                               for (size_t j = 0; j < i; j++) {
+                                       if (isaBatType(getArgType(mb, pci, j)))
+                                               
BBPunfix(*getArgReference_bat(stk, pci, j));
+                                       else
+                                               
VALclear(&stk->stk[pci->argv[j]]);
+                               }
+                               return createException(MAL, "rapi.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
+                       *getArgReference_bat(stk, pci, i) = b->batCacheid;
+                       BBPkeepref(b->batCacheid);
+               } else { // single value return, only for non-grouped 
aggregations
+                       // return NULL to conform to SQL aggregates
+                       int tpe = getArgType(mb, pci, i);
+                       if (!VALinit(&stk->stk[pci->argv[i]], tpe, 
ATOMnilptr(tpe))) {
+                               for (size_t j = 0; j < i; j++) {
+                                       if (isaBatType(getArgType(mb, pci, j)))
+                                               
BBPunfix(*getArgReference_bat(stk, pci, j));
+                                       else
+                                               
VALclear(&stk->stk[pci->argv[j]]);
+                               }
+                               return createException(MAL, "rapi.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
+               }
+       }
+       return MAL_SUCCEED;
+}
+
 static str RAPIeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, 
bit grouped) {
        sql_func * sqlfun = NULL;
        str exprStr = *getArgReference_str(stk, pci, pci->retc + 1);
@@ -656,6 +690,12 @@ static str RAPIeval(Client cntxt, MalBlk
                                msg = createException(MAL, "rapi.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
                                goto wrapup;
                        }
+                       if (BATcount(b) == 0) { /* empty input, generate 
trivial return */
+                               /* I expect all inputs to have the same size, 
so this should be safe */
+                               msg = empty_return(mb, stk, pci, pci->retc, 
b->hseqbase);
+                               BBPunfix(b->batCacheid);
+                               goto wrapup;
+                       }
                }
 
                // check the BAT count, if it is bigger than RAPI_MAX_TUPLES, 
fail
@@ -780,9 +820,9 @@ static str RAPIeval(Client cntxt, MalBlk
                }
                msg = MAL_SUCCEED;
        }
+  wrapup:
        /* unprotect environment, so it will be eaten by the GC. */
        UNPROTECT(1);
-  wrapup:
        MT_lock_unset(&rapiLock);
        if (argnames)
                free(argnames);
diff --git a/sql/backends/monet5/Tests/rapi18.test 
b/sql/backends/monet5/Tests/rapi18.test
--- a/sql/backends/monet5/Tests/rapi18.test
+++ b/sql/backends/monet5/Tests/rapi18.test
@@ -26,5 +26,17 @@ select g, rapi18(n) from rapi18bad group
 1000 values hashing to 11dbd9e3e1c8fd598a3eaf93a417a852
 
 statement ok
+create table empty_table(col1 int)
+
+query R rowsort
+select rapi18(col1) from empty_table
+----
+NULL
+
+query R rowsort
+select rapi18(col1) from empty_table group by col1
+----
+
+statement ok
 ROLLBACK
 
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi07.test 
b/sql/backends/monet5/UDF/capi/Tests/capi07.test
--- a/sql/backends/monet5/UDF/capi/Tests/capi07.test
+++ b/sql/backends/monet5/UDF/capi/Tests/capi07.test
@@ -15,7 +15,7 @@ CREATE AGGREGATE capi07(inp INTEGER) RET
 statement ok
 CREATE TABLE integers(i INTEGER)
 
-statement ok
+statement ok rowcount 6
 INSERT INTO integers VALUES (3), (4), (1), (2), (5), (6)
 
 query I rowsort
@@ -23,6 +23,18 @@ SELECT capi07(i) FROM integers
 ----
 21
 
+statement ok rowcount 6
+TRUNCATE integers
+
+query I rowsort
+SELECT capi07(i) FROM integers
+----
+NULL
+
+query I rowsort
+SELECT capi07(i) FROM integers GROUP BY i
+----
+
 statement ok
 ROLLBACK
 
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
@@ -379,6 +379,40 @@ static timestamp timestamp_from_data(cud
 
 static char valid_path_characters[] = "abcdefghijklmnopqrstuvwxyz";
 
+static str
+empty_return(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, size_t retcols, oid 
seqbase)
+{
+       for (size_t i = 0; i < retcols; i++) {
+               if (isaBatType(getArgType(mb, pci, i))) {
+                       BAT *b = COLnew(seqbase, getBatType(getArgType(mb, pci, 
i)), 0, TRANSIENT);
+                       if (!b) {
+                               for (size_t j = 0; j < i; j++) {
+                                       if (isaBatType(getArgType(mb, pci, j)))
+                                               
BBPunfix(*getArgReference_bat(stk, pci, j));
+                                       else
+                                               
VALclear(&stk->stk[pci->argv[j]]);
+                               }
+                               return createException(MAL, "cudf.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
+                       *getArgReference_bat(stk, pci, i) = b->batCacheid;
+                       BBPkeepref(b->batCacheid);
+               } else { // single value return, only for non-grouped 
aggregations
+                       // return NULL to conform to SQL aggregates
+                       int tpe = getArgType(mb, pci, i);
+                       if (!VALinit(&stk->stk[pci->argv[i]], tpe, 
ATOMnilptr(tpe))) {
+                               for (size_t j = 0; j < i; j++) {
+                                       if (isaBatType(getArgType(mb, pci, j)))
+                                               
BBPunfix(*getArgReference_bat(stk, pci, j));
+                                       else
+                                               
VALclear(&stk->stk[pci->argv[j]]);
+                               }
+                               return createException(MAL, "cudf.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
+               }
+       }
+       return MAL_SUCCEED;
+}
+
 static str CUDFeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
                                        bool grouped)
 {
@@ -971,8 +1005,19 @@ static str CUDFeval(Client cntxt, MalBlk
                } else {
                        // deal with BAT input
                        bat_type = getBatType(getArgType(mb, pci, i));
-                       input_bats[index] =
-                               BATdescriptor(*getArgReference_bat(stk, pci, 
i));
+                       if (!(input_bats[index] =
+                                 BATdescriptor(*getArgReference_bat(stk, pci, 
i)))) {
+                               msg = createException(MAL, "cudf.eval", 
MAL_MALLOC_FAIL);
+                               goto wrapup;
+                       }
+                       if (BATcount(input_bats[index]) == 0) {
+                               /* empty input, generate trivial return */
+                               /* I expect all inputs to have the same size,
+                                  so this should be safe */
+                               msg = empty_return(mb, stk, pci, output_count,
+                                                                  
input_bats[index]->hseqbase);
+                               goto wrapup;
+                       }
                }
 
                if (bat_type == TYPE_bit) {
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
@@ -53,7 +53,7 @@ typedef struct _AggrParams{
 } AggrParams;
 
 static void ComputeParallelAggregation(AggrParams *p);
-static void CreateEmptyReturn(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
+static str CreateEmptyReturn(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
                                                          size_t retcols, oid 
seqbase);
 
 static const char *FunctionBasePath(void)
@@ -296,7 +296,7 @@ static str PyAPIeval(Client cntxt, MalBl
                                // one of the input BATs is empty, don't 
execute the function at
                                // all
                                // just return empty BATs
-                               CreateEmptyReturn(mb, stk, pci, retcols, 
seqbase);
+                               msg = CreateEmptyReturn(mb, stk, pci, retcols, 
seqbase);
                                goto wrapup;
                        }
                }
@@ -1635,22 +1635,38 @@ wrapup:
        gstate = Python_ReleaseGIL(gstate);
 }
 
-static void CreateEmptyReturn(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
+static str CreateEmptyReturn(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
                                                          size_t retcols, oid 
seqbase)
 {
-       size_t i;
-       for (i = 0; i < retcols; i++) {
-               int bat_type = getBatType(getArgType(mb, pci, i));
-               BAT *b = COLnew(seqbase, bat_type, 0, TRANSIENT);
+       for (size_t i = 0; i < retcols; i++) {
                if (isaBatType(getArgType(mb, pci, i))) {
+                       BAT *b = COLnew(seqbase, getBatType(getArgType(mb, pci, 
i)), 0, TRANSIENT);
+                       if (!b) {
+                               for (size_t j = 0; j < i; j++) {
+                                       if (isaBatType(getArgType(mb, pci, j)))
+                                               
BBPunfix(*getArgReference_bat(stk, pci, j));
+                                       else
+                                               
VALclear(&stk->stk[pci->argv[j]]);
+                               }
+                               return createException(MAL, "pyapi3.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
                        *getArgReference_bat(stk, pci, i) = b->batCacheid;
                        BBPkeepref(b->batCacheid);
                } else { // single value return, only for non-grouped 
aggregations
-                       MT_lock_set(&b->theaplock);
-                       VALinit(&stk->stk[pci->argv[i]], bat_type, Tloc(b, 0));
-                       MT_lock_unset(&b->theaplock);
+                       // return NULL to conform to SQL aggregates
+                       int tpe = getArgType(mb, pci, i);
+                       if (!VALinit(&stk->stk[pci->argv[i]], tpe, 
ATOMnilptr(tpe))) {
+                               for (size_t j = 0; j < i; j++) {
+                                       if (isaBatType(getArgType(mb, pci, j)))
+                                               
BBPunfix(*getArgReference_bat(stk, pci, j));
+                                       else
+                                               
VALclear(&stk->stk[pci->argv[j]]);
+                               }
+                               return createException(MAL, "pyapi3.eval", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
                }
        }
+       return MAL_SUCCEED;
 }
 
 #include "mel.h"
diff --git a/sql/test/BugTracker-2021/Tests/All 
b/sql/test/BugTracker-2021/Tests/All
--- a/sql/test/BugTracker-2021/Tests/All
+++ b/sql/test/BugTracker-2021/Tests/All
@@ -21,3 +21,4 @@ type-upcasting-INT2BIGINT.Bug-7144
 rollup-distinct-count.Bug-7146
 sum-union.Bug-7147
 distinct-union.Bug-7148
+HAVE_LIBPY3?python-aggregates-empty.Bug-7158
diff --git 
a/sql/test/BugTracker-2021/Tests/python-aggregates-empty.Bug-7158.test 
b/sql/test/BugTracker-2021/Tests/python-aggregates-empty.Bug-7158.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2021/Tests/python-aggregates-empty.Bug-7158.test
@@ -0,0 +1,45 @@
+statement ok
+START TRANSACTION
+
+statement ok
+CREATE TABLE test (x INTEGER)
+
+statement ok
+CREATE AGGREGATE python_aggregate(val INTEGER)
+RETURNS INTEGER
+LANGUAGE PYTHON {
+    try:
+        unique = numpy.unique(aggr_group)
+        x = numpy.zeros(shape=(unique.size))
+        for i in range(0, unique.size):
+            x[i] = numpy.sum(val[aggr_group==unique[i]])
+    except NameError:
+        # aggr_group does not exist. no groups, aggregate on all data
+        x = numpy.sum(val)
+    return(x)
+}
+
+query I rowsort
+SELECT python_aggregate(x) FROM test
+----
+NULL
+
+query I rowsort
+SELECT python_aggregate(x) FROM test group by x
+----
+
+statement ok
+CREATE FUNCTION myfunc(val INTEGER)
+RETURNS INTEGER
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to