Changeset: 7b27944c15ed for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7b27944c15ed
Modified Files:
        sql/backends/monet5/UDF/pyapi/emit.c
        sql/backends/monet5/UDF/pyapi/emit.h
        sql/backends/monet5/UDF/pyapi/pyloader.c
Branch: default
Log Message:

Fix crash when no rows are emitted, and allow users to return (instead of emit) 
a dictionary as well.


diffs (143 lines):

diff --git a/sql/backends/monet5/UDF/pyapi/emit.c 
b/sql/backends/monet5/UDF/pyapi/emit.c
--- a/sql/backends/monet5/UDF/pyapi/emit.c
+++ b/sql/backends/monet5/UDF/pyapi/emit.c
@@ -28,8 +28,9 @@
         return NULL; \
     }}
 
-static PyObject *
-_emit_emit(Py_EmitObject *self, PyObject *args) {
+
+PyObject *
+PyEmit_Emit(PyEmitObject *self, PyObject *args) {
     size_t i, ai; // iterators
     ssize_t el_count = -1; // the amount of elements this emit call will write 
to the table
     size_t dict_elements, matched_elements;
@@ -306,15 +307,15 @@ wrapup:
 
 
 static PyMethodDef _emitObject_methods[] = {
-    {"emit", (PyCFunction)_emit_emit, METH_O,"emit(dictionary) -> returns 
parsed values for table insertion"},
+    {"emit", (PyCFunction)PyEmit_Emit, METH_O,"emit(dictionary) -> returns 
parsed values for table insertion"},
     {NULL,NULL,0,NULL}  /* Sentinel */
 };
 
-PyTypeObject Py_EmitType = {
+PyTypeObject PyEmitType = {
     PyObject_HEAD_INIT(NULL)
     0,
     "monetdb._emit",
-    sizeof(Py_EmitObject),
+    sizeof(PyEmitObject),
     0,
     0,                                          /* tp_dealloc */
     0,                                          /* tp_print */
@@ -366,14 +367,14 @@ PyTypeObject Py_EmitType = {
 
 
 
-PyObject *Py_Emit_Create(sql_emit_col *cols, size_t ncols)
+PyObject *PyEmit_Create(sql_emit_col *cols, size_t ncols)
 {
-    register Py_EmitObject *op;
+    register PyEmitObject *op;
 
-    op = (Py_EmitObject *)PyObject_MALLOC(sizeof(Py_EmitObject));
+    op = (PyEmitObject *)PyObject_MALLOC(sizeof(PyEmitObject));
     if (op == NULL)
         return PyErr_NoMemory();
-    PyObject_Init((PyObject*)op, &Py_EmitType);
+    PyObject_Init((PyObject*)op, &PyEmitType);
     op->cols = cols;
     op->ncols = ncols;
     op->maxcols = ncols;
@@ -385,7 +386,7 @@ PyObject *Py_Emit_Create(sql_emit_col *c
 str _emit_init(void)
 {
     _import_array();
-    if (PyType_Ready(&Py_EmitType) < 0)
+    if (PyType_Ready(&PyEmitType) < 0)
         return createException(MAL, "pyapi.eval", "Failed to initialize emit 
type.");
     return MAL_SUCCEED;
 }
diff --git a/sql/backends/monet5/UDF/pyapi/emit.h 
b/sql/backends/monet5/UDF/pyapi/emit.h
--- a/sql/backends/monet5/UDF/pyapi/emit.h
+++ b/sql/backends/monet5/UDF/pyapi/emit.h
@@ -23,11 +23,12 @@ typedef struct {
     BUN nvals;
        size_t maxcols;
        bool create_table;
-} Py_EmitObject;
+} PyEmitObject;
 
-extern PyTypeObject Py_EmitType;
+extern PyTypeObject PyEmitType;
 
-PyObject *Py_Emit_Create(sql_emit_col *cols, size_t ncols);
+PyObject *PyEmit_Create(sql_emit_col *cols, size_t ncols);
+PyObject *PyEmit_Emit(PyEmitObject *self, PyObject *args);
 
 str _emit_init(void);
 
diff --git a/sql/backends/monet5/UDF/pyapi/pyloader.c 
b/sql/backends/monet5/UDF/pyapi/pyloader.c
--- a/sql/backends/monet5/UDF/pyapi/pyloader.c
+++ b/sql/backends/monet5/UDF/pyapi/pyloader.c
@@ -151,7 +151,7 @@ str PyAPIevalLoader(Client cntxt, MalBlk
         retvals = 0;
         create_table = true;
     }
-    pEmit = Py_Emit_Create(cols, retvals);
+    pEmit = PyEmit_Create(cols, retvals);
 
     if (!pConnection || !pEmit) {
         msg = createException(MAL, "pyapi.eval_loader", MAL_MALLOC_FAIL"python 
object");
@@ -168,7 +168,7 @@ str PyAPIevalLoader(Client cntxt, MalBlk
     }
 
     {
-        PyObject *pFunc, *pModule, *v, *d;
+        PyObject *pFunc, *pModule, *v, *d, *ret;
 
         // First we will load the main module, this is required
         pModule = PyImport_AddModule("__main__");
@@ -200,17 +200,33 @@ str PyAPIevalLoader(Client cntxt, MalBlk
                 goto wrapup;
             }
         }
-        PyObject_CallObject(pFunc, pArgs);
+        ret = PyObject_CallObject(pFunc, pArgs);
 
-        cols = ((Py_EmitObject *) pEmit)->cols;
-        nval = ((Py_EmitObject *) pEmit)->nvals;
-        retvals = (int) ((Py_EmitObject *) pEmit)->ncols;
+        if (PyErr_Occurred()) {
+            Py_DECREF(pFunc);
+            Py_DECREF(pArgs);
+            msg = PyError_CreateException("Python exception", pycall);
+            if (code_object == NULL) { PyRun_SimpleString("del pyfun"); }
+            goto wrapup;
+        }
+
+        if (ret != Py_None) {
+            if (PyEmit_Emit((PyEmitObject *) pEmit, ret) == NULL) {
+                Py_DECREF(pFunc);
+                Py_DECREF(pArgs);
+                msg = PyError_CreateException("Python exception", pycall);
+                goto wrapup;
+            }
+        }
+
+        cols = ((PyEmitObject *) pEmit)->cols;
+        nval = ((PyEmitObject *) pEmit)->nvals;
+        retvals = (int) ((PyEmitObject *) pEmit)->ncols;
         Py_DECREF(pFunc);
         Py_DECREF(pArgs);
 
-        if (PyErr_Occurred()) {
-            msg = PyError_CreateException("Python exception", pycall);
-            if (code_object == NULL) { PyRun_SimpleString("del pyfun"); }
+        if (retvals == 0) {
+            msg = createException(MAL, "pyapi.eval_loader", "No elements 
emitted by the loader."); 
             goto wrapup;
         }
     }
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to