diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-09-01 19:49:26 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-09-01 19:49:26 +0000 |
| commit | 69f7084c9b79b0b70f2b24400fb150a0a40d0424 (patch) | |
| tree | 1da7f3a6b0a873472b57ad0e093339be6cff0b48 /lib/sqlalchemy/engine | |
| parent | 15ab87994ced6f27e0403ce16fd7ffada31e6858 (diff) | |
| download | sqlalchemy-69f7084c9b79b0b70f2b24400fb150a0a40d0424.tar.gz | |
- merged inline inserts branch
- all executemany() style calls put all sequences and SQL defaults inline into a single SQL statement
and don't do any pre-execution
- regular Insert and Update objects can have inline=True, forcing all executions to be inlined.
- no last_inserted_ids(), lastrow_has_defaults() available with inline execution
- calculation of pre/post execute pushed into compiler; DefaultExecutionContext greatly simplified
- fixed postgres reflection of primary key columns with no sequence/default generator, sets autoincrement=False
- fixed postgres executemany() behavior regarding sequences present, not present, passivedefaults, etc.
- all tests pass for sqlite, mysql, postgres; oracle tests pass as well as they did previously including all
insert/update/default functionality
Diffstat (limited to 'lib/sqlalchemy/engine')
| -rw-r--r-- | lib/sqlalchemy/engine/base.py | 31 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/default.py | 106 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/strategies.py | 2 |
3 files changed, 65 insertions, 74 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 496af751b..6f3badb44 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -75,6 +75,10 @@ class Dialect(object): supports_sane_rowcount Indicate whether the dialect properly implements rowcount for ``UPDATE`` and ``DELETE`` statements. + supports_sane_multi_rowcount + Indicate whether the dialect properly implements rowcount for ``UPDATE`` and ``DELETE`` statements + when executed via executemany. + """ def create_connect_args(self, url): @@ -677,7 +681,7 @@ class Connection(Connectable): try: self.__engine.dialect.do_begin(self.connection) except Exception, e: - raise exceptions.SQLError(None, None, e) + raise exceptions.DBAPIError.instance(None, None, e) def _rollback_impl(self): if self.__connection.is_valid: @@ -686,7 +690,7 @@ class Connection(Connectable): try: self.__engine.dialect.do_rollback(self.connection) except Exception, e: - raise exceptions.SQLError(None, None, e) + raise exceptions.DBAPIError.instance(None, None, e) self.__transaction = None def _commit_impl(self): @@ -696,7 +700,7 @@ class Connection(Connectable): try: self.__engine.dialect.do_commit(self.connection) except Exception, e: - raise exceptions.SQLError(None, None, e) + raise exceptions.DBAPIError.instance(None, None, e) self.__transaction = None def _savepoint_impl(self, name=None): @@ -807,12 +811,13 @@ class Connection(Connectable): return self._execute_clauseelement(func.select(), multiparams, params) def _execute_clauseelement(self, elem, multiparams=None, params=None): - executemany = multiparams is not None and len(multiparams) > 0 - if executemany: + if multiparams: param = multiparams[0] + executemany = len(multiparams) > 1 else: param = params - return self._execute_compiled(elem.compile(dialect=self.dialect, parameters=param), multiparams, params) + executemany = False + return self._execute_compiled(elem.compile(dialect=self.dialect, parameters=param, inline=executemany), multiparams, params) def _execute_compiled(self, compiled, multiparams=None, params=None): """Execute a sql.Compiled object.""" @@ -856,7 +861,7 @@ class Connection(Connectable): self._autorollback() if self.__close_with_result: self.close() - raise exceptions.SQLError(context.statement, context.parameters, e) + raise exceptions.DBAPIError.instance(context.statement, context.parameters, e) def __executemany(self, context): try: @@ -869,7 +874,7 @@ class Connection(Connectable): self._autorollback() if self.__close_with_result: self.close() - raise exceptions.SQLError(context.statement, context.parameters, e) + raise exceptions.DBAPIError.instance(context.statement, context.parameters, e) # poor man's multimethod/generic function thingy executors = { @@ -1346,12 +1351,16 @@ class ResultProxy(object): return self.context.lastrow_has_defaults() def supports_sane_rowcount(self): - """Return ``supports_sane_rowcount()`` from the underlying ExecutionContext. + """Return ``supports_sane_rowcount`` from the dialect. - See ExecutionContext for details. + """ + return self.dialect.supports_sane_rowcount + + def supports_sane_multi_rowcount(self): + """Return ``supports_sane_multi_rowcount`` from the dialect. """ - return self.context.supports_sane_rowcount() + return self.dialect.supports_sane_multi_rowcount def _get_col(self, row, key): rec = self._key_cache[key] diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 3322753bb..deea34da3 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -30,6 +30,7 @@ class DefaultDialect(base.Dialect): supports_unicode_statements = False max_identifier_length = 9999 supports_sane_rowcount = True + supports_sane_multi_rowcount = True def __init__(self, convert_unicode=False, encoding='utf-8', default_paramstyle='named', paramstyle=None, dbapi=None, **kwargs): self.convert_unicode = convert_unicode @@ -249,6 +250,9 @@ class DefaultExecutionContext(base.ExecutionContext): def supports_sane_rowcount(self): return self.dialect.supports_sane_rowcount + def supports_sane_multi_rowcount(self): + return self.dialect.supports_sane_multi_rowcount + def last_inserted_ids(self): return self._last_inserted_ids @@ -297,67 +301,45 @@ class DefaultExecutionContext(base.ExecutionContext): """generate default values for compiled insert/update statements, and generate last_inserted_ids() collection.""" - if self.isinsert: - drunner = self.dialect.defaultrunner(self) - if self.executemany: - # executemany doesn't populate last_inserted_ids() - firstparam = self.compiled_parameters[0] - processors = firstparam.get_processors() - for c in self.compiled.statement.table.c: - if c.default is not None: - params = self.compiled_parameters - for param in params: - if not c.key in param or param.get_original(c.key) is None: - self.compiled_parameters = param - newid = drunner.get_column_default(c) - if newid is not None: - param.set_value(c.key, newid) - self.compiled_parameters = params - else: - param = self.compiled_parameters - processors = param.get_processors() - last_inserted_ids = [] - for c in self.compiled.statement.table.c: - if c in self.compiled.inline_params: - self._postfetch_cols.add(c) - if c.primary_key: - last_inserted_ids.append(None) - elif not c.key in param or param.get_original(c.key) is None: - if isinstance(c.default, schema.PassiveDefault): - self._postfetch_cols.add(c) - newid = drunner.get_column_default(c) - if newid is not None: - param.set_value(c.key, newid) - if c.primary_key: - last_inserted_ids.append(param.get_processed(c.key, processors)) - elif c.primary_key: - last_inserted_ids.append(None) - elif c.primary_key: - last_inserted_ids.append(param.get_processed(c.key, processors)) - self._last_inserted_ids = last_inserted_ids - self._last_inserted_params = param - - - elif self.isupdate: - drunner = self.dialect.defaultrunner(self) + if self.isinsert or self.isupdate: if self.executemany: - for c in self.compiled.statement.table.c: - if c.onupdate is not None: - params = self.compiled_parameters - for param in params: - if not c.key in param or param.get_original(c.key) is None: - self.compiled_parameters = param - value = drunner.get_column_onupdate(c) - if value is not None: - param.set_value(c.key, value) - self.compiled_parameters = params + if len(self.compiled.prefetch): + drunner = self.dialect.defaultrunner(self) + params = self.compiled_parameters + for param in params: + self.compiled_parameters = param + for c in self.compiled.prefetch: + if self.isinsert: + val = drunner.get_column_default(c) + else: + val = drunner.get_column_onupdate(c) + if val is not None: + param.set_value(c.key, val) + self.compiled_parameters = params + else: - param = self.compiled_parameters - for c in self.compiled.statement.table.c: - if c in self.compiled.inline_params: - self._postfetch_cols.add(c) - elif c.onupdate is not None and (not c.key in param or param.get_original(c.key) is None): - value = drunner.get_column_onupdate(c) - if value is not None: - param.set_value(c.key, value) - self._last_updated_params = param + drunner = self.dialect.defaultrunner(self) + if self.isinsert: + self._last_inserted_ids = [] + for c in self.compiled.prefetch: + print "PREFETCH COL", c.key + if self.isinsert: + val = drunner.get_column_default(c) + else: + val = drunner.get_column_onupdate(c) + if val is not None: + self.compiled_parameters.set_value(c.key, val) + + if self.isinsert: + processors = self.compiled_parameters.get_processors() + for c in self.compiled.statement.table.primary_key: + if c.key in self.compiled_parameters: + self._last_inserted_ids.append(self.compiled_parameters.get_processed(c.key, processors)) + else: + self._last_inserted_ids.append(None) + + self._postfetch_cols = self.compiled.postfetch + if self.isinsert: + self._last_inserted_params = self.compiled_parameters + else: + self._last_updated_params = self.compiled_parameters diff --git a/lib/sqlalchemy/engine/strategies.py b/lib/sqlalchemy/engine/strategies.py index 7fa5d4366..524c4b0d5 100644 --- a/lib/sqlalchemy/engine/strategies.py +++ b/lib/sqlalchemy/engine/strategies.py @@ -74,7 +74,7 @@ class DefaultEngineStrategy(EngineStrategy): try: return dbapi.connect(*cargs, **cparams) except Exception, e: - raise exceptions.DBAPIError(None, None, e) + raise exceptions.DBAPIError.instance(None, None, e) creator = kwargs.pop('creator', connect) poolclass = (kwargs.pop('poolclass', None) or |
