mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 09:24:07 +03:00
Merge remote-tracking branch 'piro/devel' into devel
This commit is contained in:
commit
a59d88c703
12
NEWS
12
NEWS
|
@ -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
|
||||
---------------------------
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
17
lib/pool.py
17
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
|
||||
|
@ -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:
|
||||
# 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()
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
4
setup.py
4
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']
|
||||
|
||||
|
@ -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"))
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue
Block a user