Changeset: 90f85fc4830a for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=90f85fc4830a
Added Files:
        monetdb5/extras/pyapi/emit.c
        monetdb5/extras/pyapi/emit.h
        monetdb5/extras/pyapi/pyloader.c
        sql/backends/monet5/Tests/pyapi30.stable.err
        sql/backends/monet5/Tests/pyapi30.stable.out
        sql/backends/monet5/Tests/pyapi31.sql
        sql/backends/monet5/Tests/pyapi31.stable.err
        sql/backends/monet5/Tests/pyapi31.stable.out
Modified Files:
        monetdb5/extras/pyapi/Makefile.ag
        monetdb5/extras/pyapi/formatinput.c
        monetdb5/extras/pyapi/formatinput.h
        monetdb5/extras/pyapi/pyapi.c
        monetdb5/extras/pyapi/pyapi.h
        monetdb5/extras/pyapi/pyapi.mal
        monetdb5/extras/rapi/rapi.c
        sql/backends/monet5/Tests/All
        sql/backends/monet5/Tests/pyapi30.sql
        sql/backends/monet5/sql_gencode.c
        sql/include/sql_catalog.h
        sql/server/rel_psm.c
        sql/server/rel_select.c
        sql/server/rel_updates.c
        sql/server/sql_mvc.h
        sql/server/sql_parser.y
Branch: pythonloader
Log Message:

second stage COPY INTO sometable FROM LOADER somepythonfunction(); basic 
functionality is there


diffs (truncated from 1512 to 300 lines):

diff --git a/monetdb5/extras/pyapi/Makefile.ag 
b/monetdb5/extras/pyapi/Makefile.ag
--- a/monetdb5/extras/pyapi/Makefile.ag
+++ b/monetdb5/extras/pyapi/Makefile.ag
@@ -24,7 +24,7 @@ MTSAFE
 lib__pyapi = {
        MODULE
        DIR = libdir/monetdb5
-       SOURCES = pyapi.c pyapi.h unicode.c unicode.h pytypes.c pytypes.h 
type_conversion.c type_conversion.h  formatinput.c formatinput.h connection.c 
connection.h unspecified_evil.h
+       SOURCES = pyapi.c pyapi.h unicode.c unicode.h pytypes.c pytypes.h 
type_conversion.c type_conversion.h  formatinput.c formatinput.h connection.c 
connection.h unspecified_evil.h pyloader.c emit.h emit.c
        XDEPS = $(libpy_LIBDEP)
        LIBS = ../../tools/libmonetdb5 \
               ../../../gdk/libbat \
diff --git a/monetdb5/extras/pyapi/emit.c b/monetdb5/extras/pyapi/emit.c
new file mode 100644
--- /dev/null
+++ b/monetdb5/extras/pyapi/emit.c
@@ -0,0 +1,195 @@
+
+#include "emit.h"
+#include "type_conversion.h"
+#include "interprocess.h"
+
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#define PyString_CheckExact PyUnicode_CheckExact
+#define PyString_FromString PyUnicode_FromString
+#endif
+
+#define scalar_convert(tpe) {\
+       tpe val = (tpe) tpe##_nil; msg = pyobject_to_##tpe(&dictEntry, 42, 
&val); \
+       BUNappend(self->cols[i].b, &val, 0); \
+       if (msg != MAL_SUCCEED) { \
+               PyErr_SetString(PyExc_TypeError, "conversion failed"); /* TODO: 
better error message */ \
+               return NULL; \
+       }}
+
+static PyObject *
+_emit_emit(Py_EmitObject *self, PyObject *args) {
+       size_t i, ai;
+       ssize_t el_count = -1;
+       str msg = MAL_SUCCEED;
+       (void) self;
+       if (!PyDict_Check(args)) {
+               // complain
+               PyErr_SetString(PyExc_TypeError, "need dict");
+               return NULL;
+       }
+
+       for (i = 0; i < self->ncols; i++) {
+               PyObject *dictEntry = PyDict_GetItemString(args, 
self->cols[i].name);
+               ssize_t this_size = 1;
+               if (dictEntry) {
+                       if (!PyType_IsPyScalar(dictEntry)) {
+                               this_size = Py_SIZE(dictEntry);
+                       }
+                       if (el_count < 0) el_count = this_size;
+                       else {
+                               if (el_count != this_size) {
+                                       PyErr_SetString(PyExc_TypeError, "need 
same length values");
+                                       // todo: better error message!
+                                       return NULL;
+                               }
+                       }
+               }
+       }
+       if (el_count < 1) {
+               PyErr_SetString(PyExc_TypeError, "need at least some values");
+               // todo: better error message!
+               return NULL;
+       }
+
+       // TODO: check for dict entries not matched by any column and complain 
if present
+
+
+       for (i = 0; i < self->ncols; i++) {
+               PyObject *dictEntry = PyDict_GetItemString(args, 
self->cols[i].name);
+               if (dictEntry) {
+                       if (PyType_IsPyScalar(dictEntry)) {
+                               switch (self->cols[i].b->T->type)
+                                   {
+                                   case TYPE_bit:
+                                       scalar_convert(bit);
+                                       break;
+                                   case TYPE_bte:
+                                       scalar_convert(bte);
+                                       break;
+                                   case TYPE_sht:
+                                       scalar_convert(sht);
+                                       break;
+                                   case TYPE_int:
+                                       scalar_convert(int);
+                                       break;
+                                   case TYPE_oid:
+                                       scalar_convert(oid);
+                                       break;
+                                   case TYPE_lng:
+                                       scalar_convert(lng);
+                                       break;
+                                   case TYPE_flt:
+                                       scalar_convert(flt);
+                                       break;
+                                   case TYPE_dbl:
+                                       scalar_convert(dbl);
+                                       break;
+                               #ifdef HAVE_HGE
+                                   case TYPE_hge:
+                                       scalar_convert(hge);
+                                       break;
+                               #endif
+                                   case TYPE_str:
+                                       // FIXME scalar_convert(str);
+                                       break;
+                                   default:
+                                       break;
+                                       // complain
+                               }
+                       } else {
+                               // TODO: handle dicts with array values
+                       }
+               } else {
+                       for (ai = 0; ai < (size_t) el_count; ai++) {
+                               BUNappend(self->cols[i].b, 
ATOMnil(self->cols[i].b->T->type), 0);
+                       }
+               }
+       }
+       self->nvals += el_count;
+       Py_RETURN_NONE;
+}
+
+
+static PyMethodDef _emitObject_methods[] = {
+    {"emit", (PyCFunction)_emit_emit, METH_O,"emit(dictionary) -> returns 
parsed values for table insertion"},
+    {NULL,NULL,0,NULL}  /* Sentinel */
+};
+
+PyTypeObject Py_EmitType = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "monetdb._emit",
+    sizeof(Py_EmitObject),
+    0,
+    0,                                          /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    (hashfunc)PyObject_HashNotImplemented,      /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
+    "Value Emitter",                    /* tp_doc */
+    0,                                          /* tp_traverse */
+    0,                                          /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    _emitObject_methods,                  /* tp_methods */
+    0,                                          /* tp_members */
+    0,                                          /* tp_getset */
+    0,                                          /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    PyType_GenericAlloc,                        /* tp_alloc */
+    PyType_GenericNew,                          /* tp_new */
+    PyObject_Del,                               /* tp_free */
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, 
+    0,
+    0
+#ifdef IS_PY3K
+    ,0
+#endif
+};
+
+
+
+PyObject *Py_Emit_Create(EmitCol *cols, size_t ncols)
+{
+    register Py_EmitObject *op;
+
+    op = (Py_EmitObject *)PyObject_MALLOC(sizeof(Py_EmitObject));
+    if (op == NULL)
+        return PyErr_NoMemory();
+    PyObject_Init((PyObject*)op, &Py_EmitType);
+    op->cols = cols;
+    op->ncols = ncols;
+    op->nvals = 0;
+    return (PyObject*) op;
+}
+
+str _emit_init(void)
+{
+       _import_array();
+    if (PyType_Ready(&Py_EmitType) < 0)
+        return createException(MAL, "pyapi.eval", "Failed to initialize emit 
type.");
+    return MAL_SUCCEED;
+}
diff --git a/monetdb5/extras/pyapi/emit.h b/monetdb5/extras/pyapi/emit.h
new file mode 100644
--- /dev/null
+++ b/monetdb5/extras/pyapi/emit.h
@@ -0,0 +1,39 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2008-2015 MonetDB B.V.
+ */
+
+/*
+ * M. Raasveldt
+ * 
+ */
+
+#ifndef _LOADER_EMIT_
+#define _LOADER_EMIT_
+
+#include "pytypes.h"
+
+
+typedef struct {
+       BAT *b;
+       char* name;
+} EmitCol;
+
+typedef struct {
+    PyObject_HEAD
+       // some more stuff
+       EmitCol *cols;
+    size_t ncols;
+    size_t nvals;
+} Py_EmitObject;
+
+extern PyTypeObject Py_EmitType;
+
+PyObject *Py_Emit_Create(EmitCol *cols, size_t ncols);
+
+str _emit_init(void);
+
+#endif /* _LOADER_EMIT_ */
diff --git a/monetdb5/extras/pyapi/formatinput.c 
b/monetdb5/extras/pyapi/formatinput.c
--- a/monetdb5/extras/pyapi/formatinput.c
+++ b/monetdb5/extras/pyapi/formatinput.c
@@ -7,9 +7,6 @@
 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
 #endif
 
-const size_t additional_argcount = 3;
-const char * additional_args[] = {"_columns", "_column_types", "_conn"};
-
 #if PY_MAJOR_VERSION >= 3
 #define IS_PY3K
 #endif
@@ -61,7 +58,7 @@ PyObject *PyCodeObject_ParseString(char 
     return code_object;
 }
 
-char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, 
PyObject **code_object, char **msg)
+char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, 
PyObject **code_object, char **msg, char** additional_args, size_t 
additional_argcount)
 {
     // Format the python code by fixing the indentation levels
     // We do two passes, first we get the length of the resulting formatted 
code and then we actually create the resulting code
diff --git a/monetdb5/extras/pyapi/formatinput.h 
b/monetdb5/extras/pyapi/formatinput.h
--- a/monetdb5/extras/pyapi/formatinput.h
+++ b/monetdb5/extras/pyapi/formatinput.h
@@ -20,7 +20,7 @@
  
 extern PyObject *marshal_loads;
 
-char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, 
PyObject **code_object, char **return_message);
+char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, 
PyObject **code_object, char **msg, char** additional_args, size_t 
additional_argcount);
 
 void _formatinput_init(void);
 
diff --git a/monetdb5/extras/pyapi/pyapi.c b/monetdb5/extras/pyapi/pyapi.c
--- a/monetdb5/extras/pyapi/pyapi.c
+++ b/monetdb5/extras/pyapi/pyapi.c
@@ -36,7 +36,6 @@
 
 #endif
 
-const char* pyapi_enableflag = "embedded_py";
 const char* verbose_enableflag = "enable_pyverbose";
 const char* warning_enableflag = "enable_pywarnings";
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to