Merge branch 'close-idempotent' into devel

This commit is contained in:
Daniele Varrazzo 2012-03-05 02:47:52 +00:00
commit 37aa62ca52
7 changed files with 29 additions and 8 deletions

2
NEWS
View File

@ -1,6 +1,8 @@
What's new in psycopg 2.4.5 What's new in psycopg 2.4.5
--------------------------- ---------------------------
- The close() methods on connections and cursors don't raise exceptions
if called on already closed objects.
- Fixed fetchmany() with no argument in cursor subclasses - Fixed fetchmany() with no argument in cursor subclasses
(ticket #84). (ticket #84).
- Use lo_creat() instead of lo_create() when possible for better - Use lo_creat() instead of lo_create() when possible for better

View File

@ -906,6 +906,10 @@ conn_poll(connectionObject *self)
void void
conn_close(connectionObject *self) conn_close(connectionObject *self)
{ {
if (self->closed) {
return;
}
/* sets this connection as closed even for other threads; also note that /* sets this connection as closed even for other threads; also note that
we need to check the value of pgconn, because we get called even when we need to check the value of pgconn, because we get called even when
the connection fails! */ the connection fails! */
@ -922,14 +926,13 @@ conn_close(connectionObject *self)
* closed only in status CONN_STATUS_READY. * closed only in status CONN_STATUS_READY.
*/ */
if (self->closed == 0)
self->closed = 1; self->closed = 1;
if (self->pgconn) { if (self->pgconn) {
PQfinish(self->pgconn); PQfinish(self->pgconn);
PQfreeCancel(self->cancel);
Dprintf("conn_close: PQfinish called");
self->pgconn = NULL; self->pgconn = NULL;
Dprintf("conn_close: PQfinish called");
PQfreeCancel(self->cancel);
self->cancel = NULL; self->cancel = NULL;
} }

View File

@ -122,8 +122,6 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
static PyObject * static PyObject *
psyco_conn_close(connectionObject *self, PyObject *args) psyco_conn_close(connectionObject *self, PyObject *args)
{ {
EXC_IF_CONN_CLOSED(self);
Dprintf("psyco_conn_close: closing connection at %p", self); Dprintf("psyco_conn_close: closing connection at %p", self);
conn_close(self); conn_close(self);
Dprintf("psyco_conn_close: connection at %p closed", self); Dprintf("psyco_conn_close: connection at %p closed", self);

View File

@ -52,9 +52,12 @@ extern PyObject *pyPsycopgTzFixedOffsetTimezone;
static PyObject * static PyObject *
psyco_curs_close(cursorObject *self, PyObject *args) psyco_curs_close(cursorObject *self, PyObject *args)
{ {
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, close); EXC_IF_ASYNC_IN_PROGRESS(self, close);
if (self->closed) {
goto exit;
}
if (self->name != NULL) { if (self->name != NULL) {
char buffer[128]; char buffer[128];
@ -66,6 +69,7 @@ psyco_curs_close(cursorObject *self, PyObject *args)
self->closed = 1; self->closed = 1;
Dprintf("psyco_curs_close: cursor at %p closed", self); Dprintf("psyco_curs_close: cursor at %p closed", self);
exit:
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }

View File

@ -380,7 +380,9 @@ class DatabaseAPI20Test(unittest.TestCase):
self.assertRaises(self.driver.Error,con.commit) self.assertRaises(self.driver.Error,con.commit)
# connection.close should raise an Error if called more than once # connection.close should raise an Error if called more than once
self.assertRaises(self.driver.Error,con.close) # Issue discussed on DB-SIG: consensus seem that close() should not
# raised if called on closed objects. Issue reported back to Stuart.
# self.assertRaises(self.driver.Error,con.close)
def test_execute(self): def test_execute(self):
con = self._connect() con = self._connect()

View File

@ -48,6 +48,12 @@ class ConnectionTests(unittest.TestCase):
conn.close() conn.close()
self.assertEqual(conn.closed, True) self.assertEqual(conn.closed, True)
def test_close_idempotent(self):
conn = self.conn
conn.close()
conn.close()
self.assert_(conn.closed)
def test_cursor_closed_attribute(self): def test_cursor_closed_attribute(self):
conn = self.conn conn = self.conn
curs = conn.cursor() curs = conn.cursor()

View File

@ -37,6 +37,12 @@ class CursorTests(unittest.TestCase):
def tearDown(self): def tearDown(self):
self.conn.close() self.conn.close()
def test_close_idempotent(self):
cur = self.conn.cursor()
cur.close()
cur.close()
self.assert_(cur.closed)
def test_empty_query(self): def test_empty_query(self):
cur = self.conn.cursor() cur = self.conn.cursor()
self.assertRaises(psycopg2.ProgrammingError, cur.execute, "") self.assertRaises(psycopg2.ProgrammingError, cur.execute, "")