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