/* Replacement for PQexec using the user-provided wait function. * * The function should be called helding the connection lock, and * the GIL because some Python code is expected to be called. * * If PGresult is NULL, there may have been either a libpq error * or an exception raised by Python code: before raising an exception * check if there is already one using `PyErr_Occurred()` */ PGresult * psyco_exec_green(connectionObject *conn, const char *command) { PGresult *result = NULL; /* Send the query asynchronously */ if (0 == pq_send_query(conn, command)) { goto end; } /* Enter the poll loop with a write. When writing is finished the poll implementation will set the status to ASYNC_READ without exiting the loop. If read is finished the status is finally set to ASYNC_DONE. */ conn->async_status = ASYNC_WRITE; if (0 != psyco_wait(conn)) { psyco_clear_result_blocking(conn); goto end; } /* Now we can read the data without fear of blocking. */ result = pq_get_last_result(conn); end: conn->async_status = ASYNC_DONE; return result; }
/* Replacement for PQexec using the user-provided wait function. * * The function should be called helding the connection lock, and * the GIL because some Python code is expected to be called. * * If PGresult is NULL, there may have been either a libpq error * or an exception raised by Python code: before raising an exception * check if there is already one using `PyErr_Occurred()` */ PGresult * psyco_exec_green(connectionObject *conn, const char *command) { PGresult *result = NULL; /* Check that there is a single concurrently executing query */ if (conn->async_cursor) { PyErr_SetString(ProgrammingError, "a single async query can be executed on the same connection"); goto end; } /* we don't care about which cursor is executing the query, and * it may also be that no cursor is involved at all and this is * an internal query. So just store anything in the async_cursor, * respecting the code expecting it to be a weakref */ if (!(conn->async_cursor = PyWeakref_NewRef((PyObject*)conn, NULL))) { goto end; } /* Send the query asynchronously */ if (0 == pq_send_query(conn, command)) { goto end; } /* Enter the poll loop with a write. When writing is finished the poll implementation will set the status to ASYNC_READ without exiting the loop. If read is finished the status is finally set to ASYNC_DONE. */ conn->async_status = ASYNC_WRITE; if (0 != psyco_wait(conn)) { psyco_clear_result_blocking(conn); goto end; } /* Now we can read the data without fear of blocking. */ result = pq_get_last_result(conn); end: conn->async_status = ASYNC_DONE; Py_CLEAR(conn->async_cursor); return result; }