LCOV - code coverage report
Current view: top level - sql/backends/monet5/UDF/pyapi3 - connection3.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 57 71 80.3 %
Date: 2021-10-13 02:24:04 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "pyapi.h"
      11             : #include "conversion.h"
      12             : #include "connection.h"
      13             : #include "type_conversion.h"
      14             : #include "gdk_interprocess.h"
      15             : 
      16          13 : static PyObject *_connection_execute(Py_ConnectionObject *self, PyObject *args)
      17             : {
      18             :         char *query = NULL;
      19          13 :         if (PyString_CheckExact(args)) {
      20          13 :                 query = GDKstrdup(PyUnicode_AsUTF8(args));
      21             :         } else {
      22           0 :                 PyErr_Format(PyExc_TypeError,
      23             :                                          "expected a query string, but got an object of type %s",
      24             :                                          Py_TYPE(args)->tp_name);
      25           0 :                 return NULL;
      26             :         }
      27          13 :         if (!query) {
      28           0 :                 PyErr_Format(PyExc_Exception, "%s", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      29           0 :                 return NULL;
      30             :         }
      31          13 :         if (!self->mapped || option_disable_fork) {
      32             :                 // This is not a mapped process, so we can just directly execute the
      33             :                 // query here
      34             :                 PyObject *result;
      35           6 :                 res_table *output = NULL;
      36           6 :                 char *res = NULL;
      37             : //Py_BEGIN_ALLOW_THREADS;
      38           6 :                 res = _connection_query(self->cntxt, query, &output);
      39             : //Py_END_ALLOW_THREADS;
      40           6 :                 GDKfree(query);
      41           6 :                 if (res != MAL_SUCCEED) {
      42           2 :                         PyErr_Format(PyExc_Exception, "SQL Query Failed: %s",
      43           2 :                                                  (res ? getExceptionMessage(res) : "<no error>"));
      44           2 :                         freeException(res);
      45           2 :                         return NULL;
      46             :                 }
      47             : 
      48           4 :                 result = PyDict_New();
      49           4 :                 if (output && output->nr_cols > 0) {
      50             :                         PyInput input;
      51             :                         PyObject *numpy_array;
      52             :                         int i;
      53           8 :                         for (i = 0; i < output->nr_cols; i++) {
      54           4 :                                 res_col col = output->cols[i];
      55           4 :                                 BAT *b = BATdescriptor(col.b);
      56             : 
      57           4 :                                 if (b == NULL) {
      58           0 :                                         PyErr_Format(PyExc_Exception, "Internal error: could not retrieve bat");
      59           0 :                                         return NULL;
      60             :                                 }
      61             : 
      62           4 :                                 input.bat = b;
      63           4 :                                 input.count = BATcount(b);
      64           4 :                                 input.bat_type = getBatType(b->ttype);
      65           4 :                                 input.scalar = false;
      66           4 :                                 input.sql_subtype = &col.type;
      67             : 
      68             :                                 numpy_array =
      69           4 :                                         PyMaskedArray_FromBAT(&input, 0, input.count, &res, true);
      70           4 :                                 if (!numpy_array) {
      71           0 :                                         _connection_cleanup_result(output);
      72           0 :                                         BBPunfix(b->batCacheid);
      73           0 :                                         PyErr_Format(PyExc_Exception, "SQL Query Failed: %s",
      74           0 :                                                                  (res ? getExceptionMessage(res) : "<no error>"));
      75           0 :                                         return NULL;
      76             :                                 }
      77           4 :                                 PyDict_SetItem(result,
      78           4 :                                                            PyString_FromString(output->cols[i].name),
      79             :                                                            numpy_array);
      80             :                                 Py_DECREF(numpy_array);
      81           4 :                                 BBPunfix(input.bat->batCacheid);
      82             :                         }
      83           4 :                         _connection_cleanup_result(output);
      84           4 :                         return result;
      85             :                 } else {
      86           0 :                         Py_RETURN_NONE;
      87             :                 }
      88             :         } else {
      89           7 :                 PyErr_Format(PyExc_Exception, "Loopback queries are not supported in parallel.");
      90           7 :                 GDKfree(query);
      91           7 :                 return NULL;
      92             :         }
      93             : }
      94             : 
      95             : static PyMethodDef _connectionObject_methods[] = {
      96             :         {"execute", (PyCFunction)_connection_execute, METH_O,
      97             :          "execute(query) -> executes a SQL query on the database in the current "
      98             :          "client context"},
      99             :         {NULL, NULL, 0, NULL} /* Sentinel */
     100             : };
     101             : 
     102             : PyTypeObject Py_ConnectionType = {
     103             :         .ob_base.ob_base.ob_refcnt = 1,
     104             :         .tp_name = "monetdb._connection",
     105             :         .tp_basicsize = sizeof(Py_ConnectionObject),
     106             :         .tp_hash = (hashfunc)PyObject_HashNotImplemented,
     107             :         .tp_flags = Py_TPFLAGS_DEFAULT,
     108             :         .tp_doc = "Connection to MonetDB",
     109             :         .tp_methods = _connectionObject_methods,
     110             :         .tp_alloc = PyType_GenericAlloc,
     111             :         .tp_new = PyType_GenericNew,
     112             :         .tp_free = PyObject_Del,
     113             : };
     114             : 
     115           4 : void _connection_cleanup_result(void *output)
     116             : {
     117           4 :         SQLdestroyResult((res_table *)output);
     118           4 : }
     119             : 
     120           6 : str _connection_query(Client cntxt, const char *query, res_table **result)
     121             : {
     122             :         str res = MAL_SUCCEED;
     123           6 :         res = SQLstatementIntern(cntxt, query, "name", 1, 0, result);
     124           6 :         return res;
     125             : }
     126             : 
     127           1 : str _connection_create_table(Client cntxt, char *sname, char *tname,
     128             :                                                          sql_emit_col *columns, size_t ncols)
     129             : {
     130           1 :         return create_table_from_emit(cntxt, sname, tname, columns, ncols);
     131             : }
     132             : 
     133          12 : str _connection_append_to_table(Client cntxt, char *sname, char *tname,
     134             :                                                          sql_emit_col *columns, size_t ncols)
     135             : {
     136          12 :         return append_to_table_from_emit(cntxt, sname, tname, columns, ncols);
     137             : }
     138             : 
     139         168 : PyObject *Py_Connection_Create(Client cntxt, bit mapped, QueryStruct *query_ptr,
     140             :                                                            int query_sem)
     141             : {
     142             :         register Py_ConnectionObject *op;
     143             : 
     144         168 :         op = (Py_ConnectionObject *)PyObject_MALLOC(sizeof(Py_ConnectionObject));
     145         168 :         if (op == NULL)
     146           0 :                 return PyErr_NoMemory();
     147         168 :         PyObject_Init((PyObject *)op, &Py_ConnectionType);
     148             : 
     149         168 :         op->cntxt = cntxt;
     150         168 :         op->mapped = mapped;
     151         168 :         op->query_ptr = query_ptr;
     152         168 :         op->query_sem = query_sem;
     153             : 
     154         168 :         return (PyObject *)op;
     155             : }
     156             : 
     157           8 : static void _connection_import_array(void) { _import_array(); }
     158             : 
     159           8 : str _connection_init(void)
     160             : {
     161             :         str msg = MAL_SUCCEED;
     162             :         _connection_import_array();
     163             : 
     164             :         if (msg != MAL_SUCCEED) {
     165             :                 return msg;
     166             :         }
     167             : 
     168           8 :         if (PyType_Ready(&Py_ConnectionType) < 0)
     169           0 :                 return createException(MAL, "pyapi3.eval",
     170             :                                        SQLSTATE(PY000) "Failed to initialize connection type.");
     171             :         return msg;
     172             : }

Generated by: LCOV version 1.14