From e3b32dcee15b51897a19fb7af4afa5881af35d8f Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 30 Jun 2011 14:43:33 +0100 Subject: [PATCH 1/8] Bump to next dev version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e03876a8..a66b2195 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ except ImportError: # Take a look at http://www.python.org/dev/peps/pep-0386/ # for a consistent versioning pattern. -PSYCOPG_VERSION = '2.4.2' +PSYCOPG_VERSION = '2.4.3.dev0' version_flags = ['dt', 'dec'] From d9fce1f837151e6eadfd8ca761ef328a721198bd Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 30 Jun 2011 14:48:35 +0100 Subject: [PATCH 2/8] Mention the lazy uuid import in the news file --- NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS b/NEWS index dd595968..39af3a61 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +What's new in psycopg 2.4.3 +--------------------------- + + - Lazy import of the slow uuid module, thanks to Marko Kreen. + + What's new in psycopg 2.4.2 --------------------------- From de6f2ac387231fcd57c05031c82471ea57255e2b Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 30 Jun 2011 14:43:21 +0100 Subject: [PATCH 3/8] Grab the GIL when checking for errors occurred The problem was causing a segfault on BEGIN if the server is disconnected after the connection is created. --- NEWS | 2 ++ psycopg/pqpath.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/NEWS b/NEWS index 39af3a61..1c70c6da 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ What's new in psycopg 2.4.3 --------------------------- + - Fixed segfault in case of transaction started with connection lost + (and possibly other events). - Lazy import of the slow uuid module, thanks to Marko Kreen. diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c index cee5ce4c..1f0d5da9 100644 --- a/psycopg/pqpath.c +++ b/psycopg/pqpath.c @@ -344,11 +344,13 @@ pq_execute_command_locked(connectionObject *conn, const char *query, } if (*pgres == NULL) { Dprintf("pq_execute_command_locked: PQexec returned NULL"); + PyEval_RestoreThread(*tstate); if (!PyErr_Occurred()) { const char *msg; msg = PQerrorMessage(conn->pgconn); if (msg && *msg) { *error = strdup(msg); } } + *tstate = PyEval_SaveThread(); goto cleanup; } @@ -635,11 +637,13 @@ pq_get_guc_locked( if (*pgres == NULL) { Dprintf("pq_get_guc_locked: PQexec returned NULL"); + PyEval_RestoreThread(*tstate); if (!PyErr_Occurred()) { const char *msg; msg = PQerrorMessage(conn->pgconn); if (msg && *msg) { *error = strdup(msg); } } + *tstate = PyEval_SaveThread(); goto cleanup; } if (PQresultStatus(*pgres) != PGRES_TUPLES_OK) { From 4fd5f3267b4590eaaa619bc2db5d46e272ee4850 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 30 Jun 2011 15:53:31 +0100 Subject: [PATCH 4/8] Raise PoolError when putting a connection not belonging to the pool A KeyError was raised instead. --- lib/pool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pool.py b/lib/pool.py index 8a8fa539..51445257 100644 --- a/lib/pool.py +++ b/lib/pool.py @@ -115,7 +115,7 @@ class AbstractConnectionPool(object): def _putconn(self, conn, key=None, close=False): """Put away a connection.""" if self.closed: raise PoolError("connection pool is closed") - if key is None: key = self._rused[id(conn)] + if key is None: key = self._rused.get(id(conn)) if not key: raise PoolError("trying to put unkeyed connection") From 11ff27b5afbcb3ecfb6a14eb6820a3075369a1e6 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 30 Jun 2011 16:40:35 +0100 Subject: [PATCH 5/8] Added documentation for putconn's close parameter --- doc/src/pool.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/src/pool.rst b/doc/src/pool.rst index 9d588e16..de8132f5 100644 --- a/doc/src/pool.rst +++ b/doc/src/pool.rst @@ -26,10 +26,12 @@ directly into the client application. Get a free connection and assign it to *key* if not `!None`. - .. method:: putconn(conn, key=None) + .. method:: putconn(conn, key=None, close=False) Put away a connection. + If *close* is `!True`, discard the connection from the pool. + .. method:: closeall Close all the connections handled by the pool. From a2ee25ecfe600a3d0c5d1ea4f852f4b2b6121cfd Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 30 Jun 2011 16:44:07 +0100 Subject: [PATCH 6/8] Check the connection status before putting back into the pool Rollback connections in transaction or in error. Discard broken connections. Closes ticket #62. --- NEWS | 2 ++ lib/pool.py | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 1c70c6da..e08e68ba 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ What's new in psycopg 2.4.3 - Fixed segfault in case of transaction started with connection lost (and possibly other events). + - Rollback connections in transaction or in error before putting them + back into a pool. Also discard broken connections (ticket #62). - Lazy import of the slow uuid module, thanks to Marko Kreen. diff --git a/lib/pool.py b/lib/pool.py index 51445257..da8d3057 100644 --- a/lib/pool.py +++ b/lib/pool.py @@ -25,6 +25,7 @@ This module implements thread-safe (and not) connection pools. # License for more details. import psycopg2 +import psycopg2.extensions as _ext try: import logging @@ -121,7 +122,21 @@ class AbstractConnectionPool(object): raise PoolError("trying to put unkeyed connection") if len(self._pool) < self.minconn and not close: - self._pool.append(conn) + # Return the connection into a consistent state before putting + # it back into the pool + if not conn.closed: + status = conn.get_transaction_status() + if status == _ext.TRANSACTION_STATUS_UNKNOWN: + # server connection lost + conn.close() + elif status != _ext.TRANSACTION_STATUS_IDLE: + # connection in error or in transaction + conn.rollback() + self._pool.append(conn) + else: + # regular idle connection + self._pool.append(conn) + # If the connection is closed, we just discard it. else: conn.close() From 9870ca4dce4d3d8fa8dc56fa35559a89b34c1e1b Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 9 Aug 2011 11:29:15 +0100 Subject: [PATCH 7/8] Fixed NamedTupleCursor.executemany() (ticket #65) --- NEWS | 1 + lib/extras.py | 2 +- tests/extras_dictcursor.py | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e08e68ba..8f677dfa 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ What's new in psycopg 2.4.3 - Rollback connections in transaction or in error before putting them back into a pool. Also discard broken connections (ticket #62). - Lazy import of the slow uuid module, thanks to Marko Kreen. + - Fixed NamedTupleCursor.executemany() (ticket #65). What's new in psycopg 2.4.2 diff --git a/lib/extras.py b/lib/extras.py index a36faa8e..0d7bc981 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -275,7 +275,7 @@ class NamedTupleCursor(_cursor): def executemany(self, query, vars): self.Record = None - return _cursor.executemany(self, vars) + return _cursor.executemany(self, query, vars) def callproc(self, procname, vars=None): self.Record = None diff --git a/tests/extras_dictcursor.py b/tests/extras_dictcursor.py index 898c16c3..c74075b0 100755 --- a/tests/extras_dictcursor.py +++ b/tests/extras_dictcursor.py @@ -171,6 +171,17 @@ class NamedTupleCursorTest(unittest.TestCase): self.assertEqual(res[2].i, 3) self.assertEqual(res[2].s, 'baz') + @skip_if_no_namedtuple + def test_executemany(self): + curs = self.conn.cursor() + curs.executemany("delete from nttest where i = %s", + [(1,), (2,)]) + curs.execute("select * from nttest order by 1") + res = curs.fetchall() + self.assertEqual(1, len(res)) + self.assertEqual(res[0].i, 3) + self.assertEqual(res[0].s, 'baz') + @skip_if_no_namedtuple def test_iter(self): curs = self.conn.cursor() From 1861e0010d2a40c32a9793c5358304786f2b0d1d Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 9 Aug 2011 11:35:45 +0100 Subject: [PATCH 8/8] Fixed --static-libpq setup option (ticket #64) --- NEWS | 1 + setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8f677dfa..b044c3e9 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ What's new in psycopg 2.4.3 back into a pool. Also discard broken connections (ticket #62). - Lazy import of the slow uuid module, thanks to Marko Kreen. - Fixed NamedTupleCursor.executemany() (ticket #65). + - Fixed --static-libpq setup option (ticket #64). What's new in psycopg 2.4.2 diff --git a/setup.py b/setup.py index a66b2195..161efaef 100644 --- a/setup.py +++ b/setup.py @@ -362,7 +362,7 @@ class psycopg_build_ext(build_ext): self.include_dirs.append(".") if self.static_libpq: - if not hasattr(self, 'link_objects'): + if not getattr(self, 'link_objects', None): self.link_objects = [] self.link_objects.append( os.path.join(pg_config_helper.query("libdir"), "libpq.a"))