Changeset: d724159ab6c7 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d724159ab6c7
Modified Files:
        monetdb5/extras/pyapi/emit.c
        monetdb5/extras/pyapi/pyapi.c
        monetdb5/extras/pyapi/type_conversion.c
        monetdb5/extras/pyapi/type_conversion.h
        sql/backends/monet5/Tests/pyapi30.sql
        sql/backends/monet5/Tests/pyapi30.stable.out
Branch: pythonloader
Log Message:

Add support for strings in pyloader functions.


diffs (truncated from 653 to 300 lines):

diff --git a/monetdb5/extras/pyapi/emit.c b/monetdb5/extras/pyapi/emit.c
--- a/monetdb5/extras/pyapi/emit.c
+++ b/monetdb5/extras/pyapi/emit.c
@@ -13,7 +13,7 @@
        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 */ \
+               PyErr_Format(PyExc_TypeError, "Conversion Failed: %s", msg); \
                return NULL; \
        }}
 
@@ -91,7 +91,18 @@ static PyObject *
                                        break;
                                #endif
                                    case TYPE_str:
-                                       // FIXME scalar_convert(str);
+                    {
+                        str val = NULL;
+                        msg = pyobject_to_str(&dictEntry, 42, &val);
+                       BUNappend(self->cols[i].b, val, 0);
+                        if (val) {
+                            free(val);
+                        }
+                       if (msg != MAL_SUCCEED) {
+                               PyErr_Format(PyExc_TypeError, "Conversion 
Failed: %s", msg);
+                               return NULL;
+                       }
+                    }
                                        break;
                                    default:
                                        break;
@@ -162,7 +173,7 @@ PyTypeObject Py_EmitType = {
     0,
     0,
     0,
-    0, 
+    0,
     0,
     0
 #ifdef IS_PY3K
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
@@ -399,7 +399,7 @@ Array of type %s no copying will be need
         ptr[group][i][temp_indices[group]++] = batcontent[element_it];         
   \
     }                                                                          
   \
     GDKfree(temp_indices);                                                     
   \
-} 
+}
 
 str
 PyAPIeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bit 
grouped, bit mapped);
@@ -627,7 +627,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
 
         //create initial shared memory
         MT_lock_set(&pyapiLock);
-        mmap_id = get_unique_id(mmap_count); 
+        mmap_id = get_unique_id(mmap_count);
         MT_lock_unset(&pyapiLock);
 
         mmap_ptrs = GDKzalloc(mmap_count * sizeof(void*));
@@ -712,11 +712,11 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
                 //wait for the child to finish
                 //note that we use a timeout here in case the child crashes 
for some reason
                 //in this case the semaphore value is never increased, so we 
would be stuck otherwise
-                msg = change_semaphore_value_timeout(query_sem, 0, -1, 100, 
&sem_success); 
+                msg = change_semaphore_value_timeout(query_sem, 0, -1, 100, 
&sem_success);
                 if (msg != MAL_SUCCEED){
                     goto wrapup;
                 }
-                if (sem_success) 
+                if (sem_success)
                 {
                     if (query_ptr->pending_query) {
                         // we have to handle a query for the forked process
@@ -737,7 +737,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
                         query_ptr->nr_cols = 0;
                         query_ptr->mmapid = -1;
 
-                        if (output != NULL && output->nr_cols > 0) 
+                        if (output != NULL && output->nr_cols > 0)
                         {
                             // copy the return values into shared memory if 
there are any
                             size_t size = 0;
@@ -776,7 +776,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
                                 size += sizeof(COLrec);                        
                       //[COLrec]
                                 size += sizeof(BATrec);                        
                       //[BATrec]
                                 size += batsize;                               
                       //[DATA]
-                                
+
                                 if (b->T->vheap != NULL) {
                                     size += sizeof(Heap);                      
                       //[VHEAP]
                                     size += b->T->vheap->size;                 
                       //[VHEAPDATA]
@@ -789,7 +789,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
 
                             // create the actual shared memory region
                             MT_lock_set(&pyapiLock);
-                            query_ptr->mmapid = get_unique_id(1); 
+                            query_ptr->mmapid = get_unique_id(1);
                             MT_lock_unset(&pyapiLock);
 
                             msg = init_mmap_memory(query_ptr->mmapid, 0, size, 
NULL, NULL, &result_ptr);
@@ -808,16 +808,16 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
                                 size_t batsize = b->T->width * BATcount(b);
 
                                 //[COLNAME]
-                                memcpy(result_ptr + position, colname, 
strlen(colname) + 1); 
+                                memcpy(result_ptr + position, colname, 
strlen(colname) + 1);
                                 position += strlen(colname) + 1;
                                 //[BAT]
-                                memcpy(result_ptr + position, b, sizeof(BAT)); 
+                                memcpy(result_ptr + position, b, sizeof(BAT));
                                 position += sizeof(BAT);
                                 //[COLREC]
-                                memcpy(result_ptr + position, b->T, 
sizeof(COLrec)); 
+                                memcpy(result_ptr + position, b->T, 
sizeof(COLrec));
                                 position += sizeof(COLrec);
                                 //[BATREC]
-                                memcpy(result_ptr + position, b->S, 
sizeof(BATrec)); 
+                                memcpy(result_ptr + position, b->S, 
sizeof(BATrec));
                                 position += sizeof(BATrec);
                                 //[DATA]
                                 memcpy(result_ptr + position, Tloc(b, 
BUNfirst(b)), batsize);
@@ -935,7 +935,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
 #endif
 
     //After this point we will execute Python Code, so we need to acquire the 
GIL
-    if (!mapped) { 
+    if (!mapped) {
         gstate = Python_ObtainGIL();
     }
 
@@ -949,14 +949,14 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
             char address[1000];
             struct stat buffer;
             size_t length;
-            if (exprStr[0] == '/') { 
+            if (exprStr[0] == '/') {
                 // absolute path
                 snprintf(address, 1000, "%s", exprStr);
             } else {
                 // relative path
                 snprintf(address, 1000, "%s/%s", FunctionBasePath(), exprStr);
             }
-            if (stat(address, &buffer) < 0) { 
+            if (stat(address, &buffer) < 0) {
                 msg = createException(MAL, "pyapi.eval", "Could not find 
Python source file \"%s\".", address);
                 goto wrapup;
             }
@@ -1111,7 +1111,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
             }
 
             //now perform the actual splitting of the data, first construct 
room for splits for every group
-            // elements are structured as follows: 
+            // elements are structured as follows:
             // split_bats [groupnr] [columnnr] [elementnr]
             split_bats = GDKzalloc(group_count * sizeof(void*));
             for(group_it = 0; group_it < group_count; group_it++) {
@@ -1168,7 +1168,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
                             temp_indices = GDKzalloc(sizeof(PyObject*) * 
group_count);
                             for(element_it = 0; element_it < elements; 
element_it++) {
                                 //group of current element
-                                oid group = aggr_group_arr[element_it]; 
+                                oid group = aggr_group_arr[element_it];
                                 //append current element to proper group
                                 ptr[group][i][temp_indices[group]++] = 
batcontent[element_it];
                             }
@@ -1194,7 +1194,7 @@ str PyAPIeval(Client cntxt, MalBlkPtr mb
                 double increment;
 
                 // if there are less groups than threads, limit threads to 
amount of groups
-                threads = group_count < threads ? group_count : threads; 
+                threads = group_count < threads ? group_count : threads;
 
                 increment = (double) group_count / (double) threads;
                 // start running the threads
@@ -1698,7 +1698,7 @@ bool PyType_IsPyScalar(PyObject *object)
 {
     if (object == NULL) return false;
     return (PyArray_CheckScalar(object) || PyInt_Check(object) || 
PyFloat_Check(object) || PyLong_Check(object) || PyString_Check(object) || 
PyBool_Check(object) || PyUnicode_Check(object) || PyByteArray_Check(object)
-#ifdef IS_PY3K   
+#ifdef IS_PY3K
         || PyBytes_Check(object)
 #endif
         );
@@ -1961,7 +1961,7 @@ PyObject *PyArrayObject_FromBAT(PyInput 
                 PyObject **data = 
((PyObject**)PyArray_DATA((PyArrayObject*)vararray));
                 PyObject *obj;
                 j = 0;
-                if (unicode) {                    
+                if (unicode) {
                     if (GDK_ELIMDOUBLES(b->T->vheap)) {
                         PyObject** pyptrs = GDKzalloc(b->T->vheap->free * 
sizeof(PyObject*));
                         if (!pyptrs) {
@@ -2408,7 +2408,7 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
         case EC_DEC:
             bat_type = TYPE_dbl;
             break;
-        default: 
+        default:
             break;
     }
 
@@ -2522,11 +2522,7 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
                         PyObject *obj;
                         if (mask != NULL && (mask[index_offset * ret->count + 
iu]) == TRUE) continue;
                         obj = *((PyObject**) &data[(index_offset * ret->count 
+ iu) * ret->memory_size]);
-                        if (PyString_CheckExact(obj) || 
PyByteArray_CheckExact(obj)) {
-                            size = Py_SIZE(obj);     //Normal strings are 1 
string per character
-                        } else if (PyUnicode_CheckExact(obj)) {
-                            size = Py_SIZE(obj) * 4; //UTF32 is 4 bytes per 
character
-                        }
+                        size = pyobject_get_size(obj);
                         if (size > utf8_size) utf8_size = size;
                     }
                     utf8_string = GDKzalloc(utf8_size);
@@ -2536,51 +2532,7 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
                             BUNappend(b, str_nil, FALSE);
                         } else {
                             //we try to handle as many types as possible
-                            PyObject *obj = *((PyObject**) &data[(index_offset 
* ret->count + iu) * ret->memory_size]);
-#ifndef IS_PY3K             
-                            if (PyString_CheckExact(obj)) {
-                                char *str = ((PyStringObject*)obj)->ob_sval;
-                                if (!string_copy(str, utf8_string, strlen(str) 
+ 1, false)) {
-                                    msg = createException(MAL, "pyapi.eval", 
"Invalid string encoding used. Please return a regular ASCII string, or a 
Numpy_Unicode object.\n");
-                                    goto wrapup;
-                                }
-                            } else 
-#endif
-                            if (PyByteArray_CheckExact(obj)) {
-                                char *str = 
((PyByteArrayObject*)obj)->ob_bytes;
-                                if (!string_copy(str, utf8_string, strlen(str) 
+ 1, false)) {
-                                    msg = createException(MAL, "pyapi.eval", 
"Invalid string encoding used. Please return a regular ASCII string, or a 
Numpy_Unicode object.\n");
-                                    goto wrapup;
-                                }
-                            } else if (PyUnicode_CheckExact(obj)) {
-#ifndef IS_PY3K
-                                Py_UNICODE *str = 
(Py_UNICODE*)((PyUnicodeObject*)obj)->str;
-#if Py_UNICODE_SIZE >= 4
-                                utf32_to_utf8(0, 
((PyUnicodeObject*)obj)->length, utf8_string, str);
-#else
-                                ucs2_to_utf8(0, 
((PyUnicodeObject*)obj)->length, utf8_string, str);
-#endif
-#else
-                                char *str = PyUnicode_AsUTF8(obj);
-                                if (!string_copy(str, utf8_string, strlen(str) 
+ 1, true)) {
-                                    msg = createException(MAL, "pyapi.eval", 
"Invalid string encoding used. Please return a regular ASCII string, or a 
Numpy_Unicode object.\n");
-                                    goto wrapup;
-                                }
-#endif
-                            } else if (PyBool_Check(obj) || PyLong_Check(obj) 
|| PyInt_Check(obj) || PyFloat_Check(obj)) {
-#ifdef HAVE_HGE
-                                hge h;
-                                pyobject_to_hge(&obj, 0, &h);
-                                hge_to_string(utf8_string, h);
-#else
-                                lng h;
-                                pyobject_to_lng(&obj, 0, &h);
-                                snprintf(utf8_string, utf8string_minlength, 
LLFMT, h);
-#endif
-                            } else {
-                                msg = createException(MAL, "pyapi.eval", 
"Unrecognized Python object. Could not convert to NPY_UNICODE.\n");
-                                goto wrapup;
-                            }
+                            pyobject_to_str(((PyObject**) &data[(index_offset 
* ret->count + iu) * ret->memory_size]), utf8_size, &utf8_string);
                             BUNappend(b, utf8_string, FALSE);
                         }
                     }
@@ -2605,7 +2557,7 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
     if (ConvertableSQLType(type)) {
         BAT *result;
         msg = ConvertToSQLType(NULL, b, type, &result, &bat_type);
-        if (msg != MAL_SUCCEED) { 
+        if (msg != MAL_SUCCEED) {
             goto wrapup;
         }
         b = result;
@@ -2637,7 +2589,7 @@ int GetSQLType(sql_subtype *sql_subtype)
 str ConvertFromSQLType(Client cntxt, BAT *b, sql_subtype *sql_subtype, BAT 
**ret_bat,  int *ret_type)
 {
     str res = MAL_SUCCEED;
-    int conv_type; 
+    int conv_type;
 
     assert(sql_subtype);
     assert(sql_subtype->type);
@@ -2652,7 +2604,7 @@ str ConvertFromSQLType(Client cntxt, BAT
         case EC_DEC:
             conv_type = TYPE_dbl;
             break;
-        default: 
+        default:
             return createException(MAL, "pyapi.eval", "Convert From SQL Type: 
Unrecognized SQL type %s (%d).", sql_subtype->type->sqlname, 
sql_subtype->type->eclass);
     }
 
@@ -2683,7 +2635,7 @@ str ConvertFromSQLType(Client cntxt, BAT
             case EC_TIMESTAMP:
                 d1 = 7;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to