From: Mike Bayer Date: Thu, 14 Jun 2007 18:17:05 +0000 (+0000) Subject: - result sets from CRUD operations close their underlying cursor immediately. X-Git-Tag: rel_0_4_6~200 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=baba8281df184b59afec2a26ca4bb69dec029437;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - result sets from CRUD operations close their underlying cursor immediately. will also autoclose the connection if defined for the operation; this allows more efficient usage of connections for successive CRUD operations with less chance of "dangling connections". --- diff --git a/CHANGES b/CHANGES index dab2fd67aa..9a4d9e2093 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,10 @@ - result.last_inserted_ids() should return a list that is identically sized to the primary key constraint of the table. values that were "passively" created and not available via cursor.lastrowid will be None. + - result sets from CRUD operations close their underlying cursor immediately. + will also autoclose the connection if defined for the operation; this + allows more efficient usage of connections for successive CRUD operations + with less chance of "dangling connections". - long-identifier detection fixed to use > rather than >= for max ident length [ticket:589] - fixed bug where selectable.corresponding_column(selectable.c.col) diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index 0622958262..7573b5a8d7 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -134,11 +134,11 @@ def descriptor(): class PGExecutionContext(default.DefaultExecutionContext): - def is_select(self): - return re.match(r'SELECT', self.statement.lstrip(), re.I) and not re.search(r'FOR UPDATE\s*$', self.statement, re.I) - + def _is_server_side(self): + return self.dialect.server_side_cursors and self.is_select() and not re.search(r'FOR UPDATE(?: NOWAIT)?\s*$', self.statement, re.I) + def create_cursor(self): - if self.dialect.server_side_cursors and self.is_select(): + if self._is_server_side(): # use server-side cursors: # http://lists.initd.org/pipermail/psycopg/2007-January/005251.html ident = "c" + hex(random.randint(0, 65535))[2:] @@ -147,7 +147,7 @@ class PGExecutionContext(default.DefaultExecutionContext): return self.connection.connection.cursor() def get_result_proxy(self): - if self.dialect.server_side_cursors and self.is_select(): + if self._is_server_side(): return base.BufferedRowResultProxy(self) else: return base.ResultProxy(self) diff --git a/lib/sqlalchemy/databases/sqlite.py b/lib/sqlalchemy/databases/sqlite.py index 0d5fc45e9e..53525582f6 100644 --- a/lib/sqlalchemy/databases/sqlite.py +++ b/lib/sqlalchemy/databases/sqlite.py @@ -141,6 +141,9 @@ class SQLiteExecutionContext(default.DefaultExecutionContext): if self.compiled.isinsert: self._last_inserted_ids = [self.cursor.lastrowid] + self._last_inserted_ids[1:] super(SQLiteExecutionContext, self).post_exec() + + def is_select(self): + return re.match(r'SELECT|PRAGMA', self.statement.lstrip(), re.I) is not None class SQLiteDialect(ansisql.ANSIDialect): diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index e7eb108b53..b1e1ee5cc9 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -861,10 +861,20 @@ class ResultProxy(object): self.closed = False self.cursor = context.cursor self.__echo = logging.is_debug_enabled(context.engine.logger) - self._init_metadata() - - rowcount = property(lambda s:s.context.get_rowcount()) - connection = property(lambda s:s.context.connection) + if context.is_select(): + self._init_metadata() + self._rowcount = None + else: + self._rowcount = context.get_rowcount() + self.close() + + connection = property(lambda self:self.context.connection) + def _get_rowcount(self): + if self._rowcount is not None: + return self._rowcount + else: + return self.context.get_rowcount() + rowcount = property(_get_rowcount) def _init_metadata(self): if hasattr(self, '_ResultProxy__props'): diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 19dd623bfe..cde8ee0981 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -191,7 +191,7 @@ class DefaultExecutionContext(base.ExecutionContext): return proc(params) def is_select(self): - return re.match(r'SELECT', self.statement.lstrip(), re.I) + return re.match(r'SELECT', self.statement.lstrip(), re.I) is not None def create_cursor(self): return self.connection.connection.cursor()