Make some methods raise an exception in asynchronous mode

The methods changed are connection.commit(), rollback(), reset(),
set_isolation_level(), set_client_encoding(), lobject(), cursor(str)
as well as cursor.execute() and cursor.callproc() if another query is
in progress and cursor.executemany(), cursor.copy_{from,to,expert)().
This commit is contained in:
Jan Urbański 2010-03-31 01:50:21 +02:00 committed by Federico Di Gregorio
parent 01799e9137
commit 727670c269
5 changed files with 34 additions and 31 deletions

View File

@ -137,6 +137,11 @@ HIDDEN PyObject *conn_poll_fetch(connectionObject *self);
PyErr_SetString(InterfaceError, "connection already closed"); \
return NULL; }
#define EXC_IF_CONN_ASYNC(self, cmd) if ((self)->async == 1) { \
PyErr_SetString(ProgrammingError, #cmd " cannot be used " \
"in asynchronous mode"); \
return NULL; }
#ifdef __cplusplus
}
#endif

View File

@ -134,6 +134,7 @@ static PyObject *
psyco_conn_commit(connectionObject *self, PyObject *args)
{
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, commit);
if (!PyArg_ParseTuple(args, "")) return NULL;
@ -154,6 +155,7 @@ static PyObject *
psyco_conn_rollback(connectionObject *self, PyObject *args)
{
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, rollback);
if (!PyArg_ParseTuple(args, "")) return NULL;
@ -178,6 +180,7 @@ psyco_conn_set_isolation_level(connectionObject *self, PyObject *args)
int level = 1;
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, set_isolation_level);
if (!PyArg_ParseTuple(args, "i", &level)) return NULL;
@ -211,6 +214,7 @@ psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
size_t i, j;
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, set_client_encoding);
if (!PyArg_ParseTuple(args, "s", &enc)) return NULL;
@ -309,6 +313,7 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
}
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, lobject);
Dprintf("psyco_conn_lobject: new lobject for connection at %p", self);
Dprintf("psyco_conn_lobject: parameters: oid = %d, mode = %s",
@ -381,6 +386,7 @@ psyco_conn_reset(connectionObject *self)
int res;
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, reset);
if (pq_reset(self) < 0)
return NULL;

View File

@ -106,6 +106,17 @@ if ((self)->mark != (self)->conn->mark) { \
PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \
return NULL; }
#define EXC_IF_CURS_ASYNC(self, cmd) if ((self)->conn->async == 1) { \
PyErr_SetString(ProgrammingError, #cmd " cannot be used " \
"in asynchronous mode"); \
return NULL; }
#define EXC_IF_ASYNC_IN_PROGRESS(self, cmd) \
if ((self)->conn->async_cursor != NULL) { \
PyErr_SetString(ProgrammingError, #cmd " cannot be used " \
"while an asynchronous query is underway"); \
return NULL; }
#ifdef __cplusplus
}
#endif

View File

@ -57,6 +57,7 @@ psyco_curs_close(cursorObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "")) return NULL;
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, close);
if (self->name != NULL) {
char buffer[128];
@ -67,7 +68,6 @@ psyco_curs_close(cursorObject *self, PyObject *args)
}
self->closed = 1;
pq_clear_async(self->conn);
Dprintf("psyco_curs_close: cursor at %p closed", self);
Py_INCREF(Py_None);
@ -471,6 +471,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
}
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, execute);
if (_psyco_curs_execute(self, operation, vars, self->conn->async)) {
Py_INCREF(Py_None);
@ -502,6 +503,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
}
EXC_IF_CURS_CLOSED(self);
EXC_IF_CURS_ASYNC(self, executemany);
if (self->name != NULL) {
psyco_set_error(ProgrammingError, (PyObject*)self,
@ -509,12 +511,6 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}
if (self->conn->async == 1) {
psyco_set_error(ProgrammingError, (PyObject*)self,
"can't call .executemany() on async cursors", NULL, NULL);
return NULL;
}
if (!PyIter_Check(vars)) {
vars = iter = PyObject_GetIter(vars);
if (iter == NULL) return NULL;
@ -528,7 +524,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
}
else {
if (self->rowcount == -1)
rowcount = -1;
rowcount = -1;
else if (rowcount >= 0)
rowcount += self->rowcount;
Py_DECREF(v);
@ -649,20 +645,6 @@ _psyco_curs_prefetch(cursorObject *self)
{
int i = 0;
/* check if there is an asynchronous query in progess and block until data
is read from it */
if (self->conn->async_cursor != NULL) {
/* first check if it's the right cursor */
if (self->conn->async_cursor != (PyObject*)self) {
psyco_set_error(ProgrammingError, (PyObject*)self,
"asynchronous fetch by wrong cursor", NULL, NULL);
return -2;
}
/* now get the result */
Dprintf("_psyco_curs_prefetch: blocking until all data is read");
curs_get_last_result(self);
}
if (self->pgres == NULL || self->needsfetch) {
self->needsfetch = 0;
Dprintf("_psyco_curs_prefetch: trying to fetch data");
@ -759,7 +741,8 @@ psyco_curs_fetchone(cursorObject *self, PyObject *args)
if (args && !PyArg_ParseTuple(args, "")) return NULL;
EXC_IF_CURS_CLOSED(self)
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchone);
if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self);
@ -820,6 +803,7 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
}
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchmany);
if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self);
@ -892,6 +876,7 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
}
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchall);
if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self);
@ -959,6 +944,7 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
{ return NULL; }
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, callproc);
if (self->name != NULL) {
psyco_set_error(ProgrammingError, (PyObject*)self,
@ -1223,6 +1209,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
return NULL;
EXC_IF_CURS_CLOSED(self);
EXC_IF_CURS_ASYNC(self, copy_from);
quoted_delimiter = psycopg_escape_string((PyObject*)self->conn, sep, 0, NULL, NULL);
if (quoted_delimiter == NULL) {
@ -1327,6 +1314,7 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
return NULL;
EXC_IF_CURS_CLOSED(self);
EXC_IF_CURS_ASYNC(self, copy_to);
quoted_delimiter = psycopg_escape_string((PyObject*)self->conn, sep, 0, NULL, NULL);
if (quoted_delimiter == NULL) {
PyErr_NoMemory();
@ -1410,6 +1398,7 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs)
{ return NULL; }
EXC_IF_CURS_CLOSED(self);
EXC_IF_CURS_ASYNC(self, copy_expert);
sql = _psyco_curs_validate_sql_basic(self, sql);

View File

@ -398,7 +398,6 @@ pq_begin_locked(connectionObject *conn, PGresult **pgres, char **error)
return 0;
}
pq_clear_async(conn);
result = pq_execute_command_locked(conn, query[conn->isolation_level],
pgres, error);
if (result == 0)
@ -432,7 +431,6 @@ pq_commit(connectionObject *conn)
pthread_mutex_lock(&conn->lock);
conn->mark += 1;
pq_clear_async(conn);
retvalue = pq_execute_command_locked(conn, "COMMIT", &pgres, &error);
pthread_mutex_unlock(&conn->lock);
@ -464,7 +462,6 @@ pq_abort_locked(connectionObject *conn, PGresult **pgres, char **error)
}
conn->mark += 1;
pq_clear_async(conn);
retvalue = pq_execute_command_locked(conn, "ROLLBACK", pgres, error);
if (retvalue == 0)
conn->status = CONN_STATUS_READY;
@ -526,7 +523,6 @@ pq_reset_locked(connectionObject *conn, PGresult **pgres, char **error)
conn->pgconn, conn->isolation_level, conn->status);
conn->mark += 1;
pq_clear_async(conn);
if (conn->isolation_level > 0 && conn->status == CONN_STATUS_BEGIN) {
retvalue = pq_execute_command_locked(conn, "ABORT", pgres, error);
@ -682,10 +678,6 @@ pq_execute(cursorObject *curs, const char *query, int async)
Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&(curs->conn->lock));
/* FIXME: we should first try to cancel the query, otherwise we will block
until it completes AND until we get the result back */
pq_clear_async(curs->conn);
if (pq_begin_locked(curs->conn, &pgres, &error) < 0) {
pthread_mutex_unlock(&(curs->conn->lock));
Py_BLOCK_THREADS;