mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-10-31 07:47:30 +03:00 
			
		
		
		
	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:
		
							parent
							
								
									01799e9137
								
							
						
					
					
						commit
						727670c269
					
				|  | @ -137,6 +137,11 @@ HIDDEN PyObject *conn_poll_fetch(connectionObject *self); | ||||||
|     PyErr_SetString(InterfaceError, "connection already closed"); \ |     PyErr_SetString(InterfaceError, "connection already closed"); \ | ||||||
|     return NULL; } |     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 | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -134,6 +134,7 @@ static PyObject * | ||||||
| psyco_conn_commit(connectionObject *self, PyObject *args) | psyco_conn_commit(connectionObject *self, PyObject *args) | ||||||
| { | { | ||||||
|     EXC_IF_CONN_CLOSED(self); |     EXC_IF_CONN_CLOSED(self); | ||||||
|  |     EXC_IF_CONN_ASYNC(self, commit); | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "")) return NULL; |     if (!PyArg_ParseTuple(args, "")) return NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -154,6 +155,7 @@ static PyObject * | ||||||
| psyco_conn_rollback(connectionObject *self, PyObject *args) | psyco_conn_rollback(connectionObject *self, PyObject *args) | ||||||
| { | { | ||||||
|     EXC_IF_CONN_CLOSED(self); |     EXC_IF_CONN_CLOSED(self); | ||||||
|  |     EXC_IF_CONN_ASYNC(self, rollback); | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "")) return NULL; |     if (!PyArg_ParseTuple(args, "")) return NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -178,6 +180,7 @@ psyco_conn_set_isolation_level(connectionObject *self, PyObject *args) | ||||||
|     int level = 1; |     int level = 1; | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CONN_CLOSED(self); |     EXC_IF_CONN_CLOSED(self); | ||||||
|  |     EXC_IF_CONN_ASYNC(self, set_isolation_level); | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "i", &level)) return NULL; |     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; |     size_t i, j; | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CONN_CLOSED(self); |     EXC_IF_CONN_CLOSED(self); | ||||||
|  |     EXC_IF_CONN_ASYNC(self, set_client_encoding); | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "s", &enc)) return NULL; |     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_CLOSED(self); | ||||||
|  |     EXC_IF_CONN_ASYNC(self, lobject); | ||||||
| 
 | 
 | ||||||
|     Dprintf("psyco_conn_lobject: new lobject for connection at %p", self); |     Dprintf("psyco_conn_lobject: new lobject for connection at %p", self); | ||||||
|     Dprintf("psyco_conn_lobject:     parameters: oid = %d, mode = %s", |     Dprintf("psyco_conn_lobject:     parameters: oid = %d, mode = %s", | ||||||
|  | @ -381,6 +386,7 @@ psyco_conn_reset(connectionObject *self) | ||||||
|     int res; |     int res; | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CONN_CLOSED(self); |     EXC_IF_CONN_CLOSED(self); | ||||||
|  |     EXC_IF_CONN_ASYNC(self, reset); | ||||||
| 
 | 
 | ||||||
|     if (pq_reset(self) < 0) |     if (pq_reset(self) < 0) | ||||||
|         return NULL; |         return NULL; | ||||||
|  |  | ||||||
|  | @ -106,6 +106,17 @@ if ((self)->mark != (self)->conn->mark) {                                  \ | ||||||
|     PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \ |     PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \ | ||||||
|     return NULL; } |     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 | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -57,6 +57,7 @@ psyco_curs_close(cursorObject *self, PyObject *args) | ||||||
|     if (!PyArg_ParseTuple(args, "")) return NULL; |     if (!PyArg_ParseTuple(args, "")) return NULL; | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_ASYNC_IN_PROGRESS(self, close); | ||||||
| 
 | 
 | ||||||
|     if (self->name != NULL) { |     if (self->name != NULL) { | ||||||
|         char buffer[128]; |         char buffer[128]; | ||||||
|  | @ -67,7 +68,6 @@ psyco_curs_close(cursorObject *self, PyObject *args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     self->closed = 1; |     self->closed = 1; | ||||||
|     pq_clear_async(self->conn); |  | ||||||
|     Dprintf("psyco_curs_close: cursor at %p closed", self); |     Dprintf("psyco_curs_close: cursor at %p closed", self); | ||||||
| 
 | 
 | ||||||
|     Py_INCREF(Py_None); |     Py_INCREF(Py_None); | ||||||
|  | @ -471,6 +471,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_ASYNC_IN_PROGRESS(self, execute); | ||||||
| 
 | 
 | ||||||
|     if (_psyco_curs_execute(self, operation, vars, self->conn->async)) { |     if (_psyco_curs_execute(self, operation, vars, self->conn->async)) { | ||||||
|         Py_INCREF(Py_None); |         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_CLOSED(self); | ||||||
|  |     EXC_IF_CURS_ASYNC(self, executemany); | ||||||
| 
 | 
 | ||||||
|     if (self->name != NULL) { |     if (self->name != NULL) { | ||||||
|         psyco_set_error(ProgrammingError, (PyObject*)self, |         psyco_set_error(ProgrammingError, (PyObject*)self, | ||||||
|  | @ -509,12 +511,6 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|         return NULL; |         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)) { |     if (!PyIter_Check(vars)) { | ||||||
|         vars = iter = PyObject_GetIter(vars); |         vars = iter = PyObject_GetIter(vars); | ||||||
|         if (iter == NULL) return NULL; |         if (iter == NULL) return NULL; | ||||||
|  | @ -528,7 +524,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             if (self->rowcount == -1) |             if (self->rowcount == -1) | ||||||
| 		rowcount = -1; |                 rowcount = -1; | ||||||
|             else if (rowcount >= 0) |             else if (rowcount >= 0) | ||||||
|                 rowcount += self->rowcount; |                 rowcount += self->rowcount; | ||||||
|             Py_DECREF(v); |             Py_DECREF(v); | ||||||
|  | @ -649,20 +645,6 @@ _psyco_curs_prefetch(cursorObject *self) | ||||||
| { | { | ||||||
|     int i = 0; |     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) { |     if (self->pgres == NULL || self->needsfetch) { | ||||||
|         self->needsfetch = 0; |         self->needsfetch = 0; | ||||||
|         Dprintf("_psyco_curs_prefetch: trying to fetch data"); |         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; |     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; |     if (_psyco_curs_prefetch(self) < 0) return NULL; | ||||||
|     EXC_IF_NO_TUPLES(self); |     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_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_ASYNC_IN_PROGRESS(self, fetchmany); | ||||||
|     if (_psyco_curs_prefetch(self) < 0) return NULL; |     if (_psyco_curs_prefetch(self) < 0) return NULL; | ||||||
|     EXC_IF_NO_TUPLES(self); |     EXC_IF_NO_TUPLES(self); | ||||||
| 
 | 
 | ||||||
|  | @ -892,6 +876,7 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_ASYNC_IN_PROGRESS(self, fetchall); | ||||||
|     if (_psyco_curs_prefetch(self) < 0) return NULL; |     if (_psyco_curs_prefetch(self) < 0) return NULL; | ||||||
|     EXC_IF_NO_TUPLES(self); |     EXC_IF_NO_TUPLES(self); | ||||||
| 
 | 
 | ||||||
|  | @ -959,6 +944,7 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|     { return NULL; } |     { return NULL; } | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_ASYNC_IN_PROGRESS(self, callproc); | ||||||
| 
 | 
 | ||||||
|     if (self->name != NULL) { |     if (self->name != NULL) { | ||||||
|         psyco_set_error(ProgrammingError, (PyObject*)self, |         psyco_set_error(ProgrammingError, (PyObject*)self, | ||||||
|  | @ -1223,6 +1209,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|         return NULL; |         return NULL; | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_CURS_ASYNC(self, copy_from); | ||||||
| 
 | 
 | ||||||
|     quoted_delimiter = psycopg_escape_string((PyObject*)self->conn, sep, 0, NULL, NULL); |     quoted_delimiter = psycopg_escape_string((PyObject*)self->conn, sep, 0, NULL, NULL); | ||||||
|     if (quoted_delimiter == NULL) { |     if (quoted_delimiter == NULL) { | ||||||
|  | @ -1327,6 +1314,7 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|         return NULL; |         return NULL; | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_CURS_ASYNC(self, copy_to); | ||||||
|     quoted_delimiter = psycopg_escape_string((PyObject*)self->conn, sep, 0, NULL, NULL); |     quoted_delimiter = psycopg_escape_string((PyObject*)self->conn, sep, 0, NULL, NULL); | ||||||
|     if (quoted_delimiter == NULL) { |     if (quoted_delimiter == NULL) { | ||||||
|         PyErr_NoMemory(); |         PyErr_NoMemory(); | ||||||
|  | @ -1410,6 +1398,7 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|     { return NULL; } |     { return NULL; } | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  |     EXC_IF_CURS_ASYNC(self, copy_expert); | ||||||
| 
 | 
 | ||||||
|     sql = _psyco_curs_validate_sql_basic(self, sql); |     sql = _psyco_curs_validate_sql_basic(self, sql); | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -398,7 +398,6 @@ pq_begin_locked(connectionObject *conn, PGresult **pgres, char **error) | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pq_clear_async(conn); |  | ||||||
|     result = pq_execute_command_locked(conn, query[conn->isolation_level], |     result = pq_execute_command_locked(conn, query[conn->isolation_level], | ||||||
|                                        pgres, error); |                                        pgres, error); | ||||||
|     if (result == 0) |     if (result == 0) | ||||||
|  | @ -432,7 +431,6 @@ pq_commit(connectionObject *conn) | ||||||
|     pthread_mutex_lock(&conn->lock); |     pthread_mutex_lock(&conn->lock); | ||||||
|     conn->mark += 1; |     conn->mark += 1; | ||||||
| 
 | 
 | ||||||
|     pq_clear_async(conn); |  | ||||||
|     retvalue = pq_execute_command_locked(conn, "COMMIT", &pgres, &error); |     retvalue = pq_execute_command_locked(conn, "COMMIT", &pgres, &error); | ||||||
| 
 | 
 | ||||||
|     pthread_mutex_unlock(&conn->lock); |     pthread_mutex_unlock(&conn->lock); | ||||||
|  | @ -464,7 +462,6 @@ pq_abort_locked(connectionObject *conn, PGresult **pgres, char **error) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     conn->mark += 1; |     conn->mark += 1; | ||||||
|     pq_clear_async(conn); |  | ||||||
|     retvalue = pq_execute_command_locked(conn, "ROLLBACK", pgres, error); |     retvalue = pq_execute_command_locked(conn, "ROLLBACK", pgres, error); | ||||||
|     if (retvalue == 0) |     if (retvalue == 0) | ||||||
|         conn->status = CONN_STATUS_READY; |         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->pgconn, conn->isolation_level, conn->status); | ||||||
| 
 | 
 | ||||||
|     conn->mark += 1; |     conn->mark += 1; | ||||||
|     pq_clear_async(conn); |  | ||||||
| 
 | 
 | ||||||
|     if (conn->isolation_level > 0 && conn->status == CONN_STATUS_BEGIN) { |     if (conn->isolation_level > 0 && conn->status == CONN_STATUS_BEGIN) { | ||||||
|         retvalue = pq_execute_command_locked(conn, "ABORT", pgres, error); |         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; |     Py_BEGIN_ALLOW_THREADS; | ||||||
|     pthread_mutex_lock(&(curs->conn->lock)); |     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) { |     if (pq_begin_locked(curs->conn, &pgres, &error) < 0) { | ||||||
|         pthread_mutex_unlock(&(curs->conn->lock)); |         pthread_mutex_unlock(&(curs->conn->lock)); | ||||||
|         Py_BLOCK_THREADS; |         Py_BLOCK_THREADS; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user