summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/engine/base.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-02-28 23:51:54 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-02-28 23:51:54 +0000
commita76927f584dab481383592645a2a471fed37ecf9 (patch)
tree1303912df863199b07bdbcf4a5ffd1abf63701d6 /lib/sqlalchemy/engine/base.py
parentc366b7ec4fded0c8baabcdc6e6f15ecd81a4bf00 (diff)
downloadsqlalchemy-a76927f584dab481383592645a2a471fed37ecf9.tar.gz
- the execution sequence pulls all rowcount/last inserted ID
info from the cursor before commit() is called on the DBAPI connection in an "autocommit" scenario. This helps mxodbc with rowcount and is probably a good idea overall. - cx_oracle wants list(), not tuple(), for empty execute. - cleaned up plain SQL param handling
Diffstat (limited to 'lib/sqlalchemy/engine/base.py')
-rw-r--r--lib/sqlalchemy/engine/base.py55
1 files changed, 41 insertions, 14 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index b4f2524d6..46907dfcf 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -77,6 +77,10 @@ class Dialect(object):
execution_ctx_cls
a :class:`ExecutionContext` class used to handle statement execution
+ execute_sequence_format
+ either the 'tuple' or 'list' type, depending on what cursor.execute()
+ accepts for the second argument (they vary).
+
preparer
a :class:`~sqlalchemy.sql.compiler.IdentifierPreparer` class used to
quote identifiers.
@@ -1055,6 +1059,7 @@ class Connection(Connectable):
In the case of 'raw' execution which accepts positional parameters,
it may be a list of tuples or lists.
+
"""
if not multiparams:
@@ -1104,7 +1109,9 @@ class Connection(Connectable):
keys = []
context = self.__create_execution_context(
- compiled_sql=elem.compile(dialect=self.dialect, column_keys=keys, inline=len(params) > 1),
+ compiled_sql=elem.compile(
+ dialect=self.dialect, column_keys=keys,
+ inline=len(params) > 1),
parameters=params
)
return self.__execute_context(context)
@@ -1128,9 +1135,15 @@ class Connection(Connectable):
context.pre_exec()
if context.executemany:
- self._cursor_executemany(context.cursor, context.statement, context.parameters, context=context)
+ self._cursor_executemany(
+ context.cursor,
+ context.statement,
+ context.parameters, context=context)
else:
- self._cursor_execute(context.cursor, context.statement, context.parameters[0], context=context)
+ self._cursor_execute(
+ context.cursor,
+ context.statement,
+ context.parameters[0], context=context)
if context.compiled:
context.post_exec()
@@ -1138,10 +1151,17 @@ class Connection(Connectable):
if context.isinsert and not context.executemany:
context.post_insert()
+ # create a resultproxy, get rowcount/implicit RETURNING
+ # rows, close cursor if no further results pending
+ r = context.get_result_proxy()._autoclose()
+
if self.__transaction is None and context.should_autocommit:
self._commit_impl()
-
- return context.get_result_proxy()._autoclose()
+
+ if r.closed and self.should_close_with_result:
+ self.close()
+
+ return r
def _handle_dbapi_exception(self, e, statement, parameters, cursor, context):
if getattr(self, '_reentrant_error', False):
@@ -1893,6 +1913,7 @@ class ResultProxy(object):
_process_row = RowProxy
out_parameters = None
+ _can_close_connection = False
def __init__(self, context):
self.context = context
@@ -1904,7 +1925,6 @@ class ResultProxy(object):
context.engine._should_log_debug()
self._init_metadata()
-
def _init_metadata(self):
metadata = self._cursor_description()
if metadata is None:
@@ -1962,21 +1982,26 @@ class ResultProxy(object):
return self.cursor.description
def _autoclose(self):
+ """called by the Connection to autoclose cursors that have no pending results
+ beyond those used by an INSERT/UPDATE/DELETE with no explicit RETURNING clause.
+
+ """
if self.context.isinsert:
if self.context._is_implicit_returning:
self.context._fetch_implicit_returning(self)
- self.close()
+ self.close(_autoclose_connection=False)
elif not self.context._is_explicit_returning:
- self.close()
+ self.close(_autoclose_connection=False)
elif self._metadata is None:
# no results, get rowcount
- # (which requires open cursor on some DB's such as firebird),
+ # (which requires open cursor on some drivers
+ # such as kintersbasdb, mxodbc),
self.rowcount
- self.close() # autoclose
-
+ self.close(_autoclose_connection=False)
+
return self
-
- def close(self):
+
+ def close(self, _autoclose_connection=True):
"""Close this ResultProxy.
Closes the underlying DBAPI cursor corresponding to the execution.
@@ -1992,12 +2017,14 @@ class ResultProxy(object):
* all result rows are exhausted using the fetchXXX() methods.
* cursor.description is None.
+
"""
if not self.closed:
self.closed = True
self.cursor.close()
- if self.connection.should_close_with_result:
+ if _autoclose_connection and \
+ self.connection.should_close_with_result:
self.connection.close()
def __iter__(self):