From: Mike Bayer Date: Sat, 23 Sep 2006 20:18:41 +0000 (+0000) Subject: - connection pool tracks open cursors and raises an error if connection X-Git-Tag: rel_0_3_0~137 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=68e893d21af31edd2bbc6dec608c95457eaffde6;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - connection pool tracks open cursors and raises an error if connection is returned to pool with cursors still opened. fixes issues with MySQL, others --- diff --git a/CHANGES b/CHANGES index e077877c36..438b1993f6 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,9 @@ to before_XXXX and after_XXXX - added autoincrement=True to Column; will disable schema generation of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if explicitly set to False +- connection pool tracks open cursors and raises an error if connection +is returned to pool with cursors still opened. fixes issues with MySQL, +others 0.2.8 - cleanup on connection methods + documentation. custom DBAPI diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index cf321bca2b..28d5ea94e6 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -211,6 +211,7 @@ class Connection(Connectable): if self.__engine.echo: self.__engine.log("ROLLBACK") self.__engine.dialect.do_rollback(self.connection) + self.__connection.close_open_cursors() self.__transaction = None def _commit_impl(self): if self.__engine.echo: @@ -643,7 +644,7 @@ class ResultProxy: # and not just plain tuples ? self.close() return None - + class RowProxy: """proxies a single cursor row for a parent ResultProxy.""" def __init__(self, parent, row): diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py index de987278d4..9eb9cd2ff8 100644 --- a/lib/sqlalchemy/pool.py +++ b/lib/sqlalchemy/pool.py @@ -168,6 +168,7 @@ class _ConnectionFairy(object): """proxies a DBAPI connection object and provides return-on-dereference support""" def __init__(self, pool): self._threadfairy = _ThreadFairy(self) + self.cursors = weakref.WeakKeyDictionary() self.__pool = pool self.__counter = 0 try: @@ -182,6 +183,7 @@ class _ConnectionFairy(object): def invalidate(self): self._connection_record.invalidate() self.connection = None + self.cursors = None self._close() def cursor(self, *args, **kwargs): try: @@ -196,6 +198,9 @@ class _ConnectionFairy(object): raise "this connection is closed" self.__counter +=1 return self + def close_open_cursors(self): + for c in list(self.cursors): + c.close() def close(self): self.__counter -=1 if self.__counter == 0: @@ -203,6 +208,8 @@ class _ConnectionFairy(object): def __del__(self): self._close() def _close(self): + if self.cursors is not None and len(self.cursors): + raise exceptions.InvalidRequestError("This connection still has %d open cursors" % len(self.cursors)) if self.connection is not None: try: self.connection.rollback() @@ -219,7 +226,12 @@ class _ConnectionFairy(object): class _CursorFairy(object): def __init__(self, parent, cursor): self.__parent = parent + self.__parent.cursors[self]=True self.cursor = cursor + def close(self): + if self in self.__parent.cursors: + del self.__parent.cursors[self] + self.cursor.close() def __getattr__(self, key): return getattr(self.cursor, key)