* psycopg/connection_int.c (conn_close): fix for new

pq_abort_locked() prototype.
	(conn_switch_isolation_level): fix for new pq_abort_locked()
	prototype, and use pq_complete_error() to show error message.
	(conn_set_client_encoding): same here.

	* psycopg/pqpath.c (pq_execute_command_locked): remove static
	modifier.
	(pq_complete_error): same here.
	(pq_abort_locked): add pgres and error arguments.
	(pq_abort): call pq_abort_locked() to reduce code duplication.
This commit is contained in:
James Henstridge 2008-01-10 18:14:44 +00:00
parent d190d5918a
commit 729117af8b
4 changed files with 53 additions and 32 deletions

View File

@ -1,3 +1,17 @@
2008-01-11 James Henstridge <james@jamesh.id.au>
* psycopg/connection_int.c (conn_close): fix for new
pq_abort_locked() prototype.
(conn_switch_isolation_level): fix for new pq_abort_locked()
prototype, and use pq_complete_error() to show error message.
(conn_set_client_encoding): same here.
* psycopg/pqpath.c (pq_execute_command_locked): remove static
modifier.
(pq_complete_error): same here.
(pq_abort_locked): add pgres and error arguments.
(pq_abort): call pq_abort_locked() to reduce code duplication.
2007-12-23 James Henstridge <james@jamesh.id.au> 2007-12-23 James Henstridge <james@jamesh.id.au>
* psycopg/pqpath.c (pq_execute_command_locked): add an error * psycopg/pqpath.c (pq_execute_command_locked): add an error

View File

@ -217,7 +217,14 @@ conn_close(connectionObject *self)
/* execute a forced rollback on the connection (but don't check the /* execute a forced rollback on the connection (but don't check the
result, we're going to close the pq connection anyway */ result, we're going to close the pq connection anyway */
if (self->pgconn) { if (self->pgconn) {
pq_abort_locked(self); PGresult *pgres = NULL;
char *error = NULL;
if (pq_abort_locked(self, &pgres, &error) < 0) {
IFCLEARPGRES(pgres);
if (error)
free (error);
}
PQfinish(self->pgconn); PQfinish(self->pgconn);
Dprintf("conn_close: PQfinish called"); Dprintf("conn_close: PQfinish called");
self->pgconn = NULL; self->pgconn = NULL;
@ -257,6 +264,8 @@ conn_rollback(connectionObject *self)
int int
conn_switch_isolation_level(connectionObject *self, int level) conn_switch_isolation_level(connectionObject *self, int level)
{ {
PGresult *pgres = NULL;
char *error = NULL;
int res = 0; int res = 0;
/* if the current isolation level is equal to the requested one don't switch */ /* if the current isolation level is equal to the requested one don't switch */
@ -268,7 +277,7 @@ conn_switch_isolation_level(connectionObject *self, int level)
/* if the current isolation level is > 0 we need to abort the current /* if the current isolation level is > 0 we need to abort the current
transaction before changing; that all folks! */ transaction before changing; that all folks! */
if (self->isolation_level != level && self->isolation_level > 0) { if (self->isolation_level != level && self->isolation_level > 0) {
res = pq_abort_locked(self); res = pq_abort_locked(self, &pgres, &error);
} }
self->isolation_level = level; self->isolation_level = level;
self->mark++; self->mark++;
@ -278,6 +287,9 @@ conn_switch_isolation_level(connectionObject *self, int level)
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (res < 0)
pq_complete_error(self, &pgres, &error);
return res; return res;
} }
@ -286,7 +298,8 @@ conn_switch_isolation_level(connectionObject *self, int level)
int int
conn_set_client_encoding(connectionObject *self, char *enc) conn_set_client_encoding(connectionObject *self, char *enc)
{ {
PGresult *pgres; PGresult *pgres = NULL;
char *error = NULL;
char query[48]; char query[48];
int res = 0; int res = 0;
@ -304,30 +317,25 @@ conn_set_client_encoding(connectionObject *self, char *enc)
/* abort the current transaction, to set the encoding ouside of /* abort the current transaction, to set the encoding ouside of
transactions */ transactions */
res = pq_abort_locked(self); res = pq_abort_locked(self, &pgres, &error);
if (res == 0) { if (res == 0) {
pgres = PQexec(self->pgconn, query); res = pq_execute_command_locked(self, query, &pgres, &error);
if (res == 0) {
if (pgres == NULL || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
res = -1;
}
else {
/* no error, we can proceeed and store the new encoding */ /* no error, we can proceeed and store the new encoding */
if (self->encoding) free(self->encoding); if (self->encoding) free(self->encoding);
self->encoding = strdup(enc); self->encoding = strdup(enc);
Dprintf("conn_set_client_encoding: set encoding to %s",
self->encoding);
} }
IFCLEARPGRES(pgres);
} }
Dprintf("conn_set_client_encoding: set encoding to %s", self->encoding);
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (res == -1) if (res < 0)
PyErr_Format(OperationalError, "can't set encoding to %s", enc); pq_complete_error(self, &pgres, &error);
return res; return res;
} }

View File

@ -238,7 +238,7 @@ pq_clear_async(connectionObject *conn)
On error, -1 is returned, and the pgres argument will hold the On error, -1 is returned, and the pgres argument will hold the
relevant result structure. relevant result structure.
*/ */
static int int
pq_execute_command_locked(connectionObject *conn, const char *query, pq_execute_command_locked(connectionObject *conn, const char *query,
PGresult **pgres, char **error) PGresult **pgres, char **error)
{ {
@ -280,7 +280,7 @@ pq_execute_command_locked(connectionObject *conn, const char *query,
This function should be called while holding the global interpreter This function should be called while holding the global interpreter
lock. lock.
*/ */
static void void
pq_complete_error(connectionObject *conn, PGresult **pgres, char **error) pq_complete_error(connectionObject *conn, PGresult **pgres, char **error)
{ {
Dprintf("pq_complete_error: pgconn = %p, pgres = %p, error = %s", Dprintf("pq_complete_error: pgconn = %p, pgres = %p, error = %s",
@ -375,11 +375,9 @@ pq_commit(connectionObject *conn)
} }
int int
pq_abort_locked(connectionObject *conn) pq_abort_locked(connectionObject *conn, PGresult **pgres, char **error)
{ {
int retvalue = -1; int retvalue = -1;
PGresult *pgres = NULL;
char *error = NULL;
Dprintf("pq_abort_locked: pgconn = %p, isolevel = %ld, status = %d", Dprintf("pq_abort_locked: pgconn = %p, isolevel = %ld, status = %d",
conn->pgconn, conn->isolation_level, conn->status); conn->pgconn, conn->isolation_level, conn->status);
@ -390,14 +388,10 @@ pq_abort_locked(connectionObject *conn)
} }
pq_clear_async(conn); 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)
conn->status = CONN_STATUS_READY;
if (retvalue < 0)
pq_set_critical(conn, NULL);
IFCLEARPGRES(pgres);
if (error)
free(error);
return retvalue; return retvalue;
} }
@ -424,16 +418,13 @@ pq_abort(connectionObject *conn)
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&conn->lock); pthread_mutex_lock(&conn->lock);
pq_clear_async(conn); retvalue = pq_abort_locked(conn, &pgres, &error);
retvalue = pq_execute_command_locked(conn, "ROLLBACK", &pgres, &error);
pthread_mutex_unlock(&conn->lock); pthread_mutex_unlock(&conn->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (retvalue < 0) if (retvalue < 0)
pq_complete_error(conn, &pgres, &error); pq_complete_error(conn, &pgres, &error);
else
conn->status = CONN_STATUS_READY;
return retvalue; return retvalue;
} }

View File

@ -33,10 +33,18 @@
extern int pq_fetch(cursorObject *curs); extern int pq_fetch(cursorObject *curs);
extern int pq_execute(cursorObject *curs, const char *query, int async); extern int pq_execute(cursorObject *curs, const char *query, int async);
extern int pq_commit(connectionObject *conn); extern int pq_commit(connectionObject *conn);
extern int pq_abort_locked(connectionObject *conn); extern int pq_abort_locked(connectionObject *conn, PGresult **pgres,
char **error);
extern int pq_abort(connectionObject *conn); extern int pq_abort(connectionObject *conn);
extern int pq_is_busy(connectionObject *conn); extern int pq_is_busy(connectionObject *conn);
extern void pq_set_critical(connectionObject *conn, const char *msg); extern void pq_set_critical(connectionObject *conn, const char *msg);
extern PyObject *pq_resolve_critical(connectionObject *conn, int close); extern PyObject *pq_resolve_critical(connectionObject *conn, int close);
extern int pq_execute_command_locked(connectionObject *conn,
const char *query,
PGresult **pgres, char **error);
extern void pq_complete_error(connectionObject *conn, PGresult **pgres,
char **error);
#endif /* !defined(PSYCOPG_PQPATH_H) */ #endif /* !defined(PSYCOPG_PQPATH_H) */