Merge remote-tracking branch 'piro/devel' into devel

This commit is contained in:
Federico Di Gregorio 2011-08-10 18:36:24 +02:00
commit a59d88c703
7 changed files with 50 additions and 6 deletions

12
NEWS
View File

@ -1,3 +1,15 @@
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.
- Fixed NamedTupleCursor.executemany() (ticket #65).
- Fixed --static-libpq setup option (ticket #64).
What's new in psycopg 2.4.2
---------------------------

View File

@ -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.

View File

@ -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

View File

@ -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
@ -115,13 +116,27 @@ 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")
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()

View File

@ -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) {

View File

@ -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']
@ -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"))

View File

@ -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()