- Added accessors to ResultProxy "returns_rows", "is_insert"
[ticket:2089]
+- engine
+ - Fixed bug in QueuePool, SingletonThreadPool whereby
+ connections that were discarded via overflow or periodic
+ cleanup() were not explicitly closed, leaving garbage
+ collection to the task instead. This generally only
+ affects non-reference-counting backends like Jython
+ and Pypy. Thanks to Jaimy Azle for spotting
+ this. [ticket:2102]
+
- postgresql
- When explicit sequence execution derives the name
of the auto-generated sequence of a SERIAL column,
def _cleanup(self):
while len(self._all_conns) > self.size:
- self._all_conns.pop()
+ c = self._all_conns.pop()
+ c.close()
def status(self):
return "SingletonThreadPool id:%d size: %d" % \
try:
self._pool.put(conn, False)
except sqla_queue.Full:
+ conn.close()
if self._overflow_lock is None:
self._overflow -= 1
else:
lazy_gc()
assert not pool._refs
+ def test_overflow_no_gc_tlocal(self):
+ self._test_overflow_no_gc(True)
+
+ def test_overflow_no_gc(self):
+ self._test_overflow_no_gc(False)
+
+ def _test_overflow_no_gc(self, threadlocal):
+ p = self._queuepool_fixture(pool_size=2,
+ max_overflow=2)
+
+ # disable weakref collection of the
+ # underlying connections
+ strong_refs = set()
+ def _conn():
+ c = p.connect()
+ strong_refs.add(c.connection)
+ return c
+
+ for j in xrange(5):
+ conns = [_conn() for i in xrange(4)]
+ for c in conns:
+ c.close()
+
+ still_opened = len([c for c in strong_refs if not c.closed])
+ eq_(still_opened, 2)
+
def test_weakref_kaboom(self):
p = self._queuepool_fixture(pool_size=3,
max_overflow=-1, use_threadlocal=True)
class SingletonThreadPoolTest(PoolTestBase):
def test_cleanup(self):
+ self._test_cleanup(False)
+
+ def test_cleanup_no_gc(self):
+ self._test_cleanup(True)
+
+ def _test_cleanup(self, strong_refs):
"""test that the pool's connections are OK after cleanup() has
been called."""
p = pool.SingletonThreadPool(creator=dbapi.connect,
pool_size=3)
+ if strong_refs:
+ sr = set()
+ def _conn():
+ c = p.connect()
+ sr.add(c.connection)
+ return c
+ else:
+ def _conn():
+ return p.connect()
+
def checkout():
for x in xrange(10):
- c = p.connect()
+ c = _conn()
assert c
c.cursor()
c.close()
th.join()
assert len(p._all_conns) == 3
+ if strong_refs:
+ still_opened = len([c for c in sr if not c.closed])
+ eq_(still_opened, 3)
+
class AssertionPoolTest(PoolTestBase):
def test_connect_error(self):
dbapi = MockDBAPI()