From 66cd772094f22e78cd044c40aa3c72ced6493d2a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 1 Nov 2007 03:58:21 +0000 Subject: [PATCH] - merged factor_down_bindparams branch. - removed ClauseParameters object; compiled.params returns a regular dictionary now, as well as result.last_inserted_params()/last_updated_params(). - various code trimming, method removals. --- CHANGES | 3 + doc/build/content/sqlexpression.txt | 6 +- lib/sqlalchemy/engine/base.py | 71 ++++++++++--------- lib/sqlalchemy/engine/default.py | 104 ++++++++++++++++++++-------- lib/sqlalchemy/orm/mapper.py | 4 +- lib/sqlalchemy/sql/compiler.py | 29 +++----- lib/sqlalchemy/sql/util.py | 101 --------------------------- test/profiling/zoomark.py | 14 ++-- test/sql/query.py | 3 +- test/sql/select.py | 16 +++-- test/testlib/testing.py | 8 +-- 11 files changed, 148 insertions(+), 211 deletions(-) diff --git a/CHANGES b/CHANGES index e7501fd674..c05ef21881 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,9 @@ CHANGES - Removed unused util.hash(). +- removed ClauseParameters object; compiled.params returns a regular dictionary + now, as well as result.last_inserted_params()/last_updated_params(). + - fixed INSERT statements w.r.t. primary key columns that have SQL-expression based default generators on them; SQL expression executes inline as normal but will not trigger a "postfetch" condition for the column, for those DB's diff --git a/doc/build/content/sqlexpression.txt b/doc/build/content/sqlexpression.txt index d8017b8336..9bf4b317ec 100644 --- a/doc/build/content/sqlexpression.txt +++ b/doc/build/content/sqlexpression.txt @@ -95,7 +95,7 @@ Above, while the `values` keyword limited the VALUES clause to just two columns, {python} >>> ins.compile().params #doctest: +NORMALIZE_WHITESPACE - ClauseParameters:{'fullname': 'Jack Jones', 'name': 'jack'} + {'fullname': 'Jack Jones', 'name': 'jack'} ## Executing {@name=executing} @@ -334,7 +334,7 @@ The `7` literal is embedded in `ClauseElement`; we can use the same trick we did {python} >>> (users.c.id==7).compile().params - ClauseParameters:{'users_id': 7} + {'users_id': 7} Most Python operators, as it turns out, produce a SQL expression here, like equals, not equals, etc.: @@ -740,7 +740,7 @@ If we wanted to use our `calculate` statement twice with different bind paramete WHERE users.id BETWEEN c1.z AND c2.z >>> s.compile().params - ClauseParameters:{'y': 45, 'x': 17, 'y_1': 12, 'x_1': 5} + {'y': 45, 'x': 17, 'y_1': 12, 'x_1': 5} ### Unions and Other Set Operations {@name=unions} diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 880362938d..660d546047 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -528,7 +528,7 @@ class Connection(Connectable): ``contextual_connect()`` methods of Engine. """ - self.__engine = engine + self.engine = engine self.__connection = connection or engine.raw_connection() self.__transaction = None self.__close_with_result = close_with_result @@ -549,10 +549,9 @@ class Connection(Connectable): This is used to execute "sub" statements within a single execution, usually an INSERT statement. """ - return Connection(self.__engine, self.__connection, _branch=True) + return Connection(self.engine, self.__connection, _branch=True) - engine = property(lambda s:s.__engine, doc="The Engine with which this Connection is associated.") - dialect = property(lambda s:s.__engine.dialect, doc="Dialect used by this Connection.") + dialect = property(lambda s:s.engine.dialect, doc="Dialect used by this Connection.") connection = property(_get_connection, doc="The underlying DB-API connection managed by this Connection.") should_close_with_result = property(lambda s:s.__close_with_result, doc="Indicates if this Connection should be closed when a corresponding ResultProxy is closed; this is essentially an auto-release mode.") properties = property(lambda s: s._get_connection().properties, @@ -652,18 +651,18 @@ class Connection(Connectable): "Cannot start a two phase transaction when a transaction " "is already in progress.") if xid is None: - xid = self.__engine.dialect.create_xid(); + xid = self.engine.dialect.create_xid(); self.__transaction = TwoPhaseTransaction(self, xid) return self.__transaction def recover_twophase(self): - return self.__engine.dialect.do_recover_twophase(self) + return self.engine.dialect.do_recover_twophase(self) def rollback_prepared(self, xid, recover=False): - self.__engine.dialect.do_rollback_twophase(self, xid, recover=recover) + self.engine.dialect.do_rollback_twophase(self, xid, recover=recover) def commit_prepared(self, xid, recover=False): - self.__engine.dialect.do_commit_twophase(self, xid, recover=recover) + self.engine.dialect.do_commit_twophase(self, xid, recover=recover) def in_transaction(self): """Return True if a transaction is in progress.""" @@ -671,28 +670,28 @@ class Connection(Connectable): return self.__transaction is not None def _begin_impl(self): - if self.__engine._should_log_info: - self.__engine.logger.info("BEGIN") + if self.engine._should_log_info: + self.engine.logger.info("BEGIN") try: - self.__engine.dialect.do_begin(self.__connection) + self.engine.dialect.do_begin(self.__connection) except Exception, e: raise exceptions.DBAPIError.instance(None, None, e) def _rollback_impl(self): if self.__connection.is_valid: - if self.__engine._should_log_info: - self.__engine.logger.info("ROLLBACK") + if self.engine._should_log_info: + self.engine.logger.info("ROLLBACK") try: - self.__engine.dialect.do_rollback(self.__connection) + self.engine.dialect.do_rollback(self.__connection) except Exception, e: raise exceptions.DBAPIError.instance(None, None, e) self.__transaction = None def _commit_impl(self): - if self.__engine._should_log_info: - self.__engine.logger.info("COMMIT") + if self.engine._should_log_info: + self.engine.logger.info("COMMIT") try: - self.__engine.dialect.do_commit(self.__connection) + self.engine.dialect.do_commit(self.__connection) except Exception, e: raise exceptions.DBAPIError.instance(None, None, e) self.__transaction = None @@ -702,38 +701,38 @@ class Connection(Connectable): self.__savepoint_seq += 1 name = 'sa_savepoint_%s' % self.__savepoint_seq if self.__connection.is_valid: - self.__engine.dialect.do_savepoint(self, name) + self.engine.dialect.do_savepoint(self, name) return name def _rollback_to_savepoint_impl(self, name, context): if self.__connection.is_valid: - self.__engine.dialect.do_rollback_to_savepoint(self, name) + self.engine.dialect.do_rollback_to_savepoint(self, name) self.__transaction = context def _release_savepoint_impl(self, name, context): if self.__connection.is_valid: - self.__engine.dialect.do_release_savepoint(self, name) + self.engine.dialect.do_release_savepoint(self, name) self.__transaction = context def _begin_twophase_impl(self, xid): if self.__connection.is_valid: - self.__engine.dialect.do_begin_twophase(self, xid) + self.engine.dialect.do_begin_twophase(self, xid) def _prepare_twophase_impl(self, xid): if self.__connection.is_valid: assert isinstance(self.__transaction, TwoPhaseTransaction) - self.__engine.dialect.do_prepare_twophase(self, xid) + self.engine.dialect.do_prepare_twophase(self, xid) def _rollback_twophase_impl(self, xid, is_prepared): if self.__connection.is_valid: assert isinstance(self.__transaction, TwoPhaseTransaction) - self.__engine.dialect.do_rollback_twophase(self, xid, is_prepared) + self.engine.dialect.do_rollback_twophase(self, xid, is_prepared) self.__transaction = None def _commit_twophase_impl(self, xid, is_prepared): if self.__connection.is_valid: assert isinstance(self.__transaction, TwoPhaseTransaction) - self.__engine.dialect.do_commit_twophase(self, xid, is_prepared) + self.engine.dialect.do_commit_twophase(self, xid, is_prepared) self.__transaction = None def _autocommit(self, context): @@ -784,7 +783,7 @@ class Connection(Connectable): raise exceptions.InvalidRequestError("Unexecutable object type: " + str(type(object))) def _execute_default(self, default, multiparams=None, params=None): - return self.__engine.dialect.defaultrunner(self.__create_execution_context()).traverse_single(default) + return self.engine.dialect.defaultrunner(self.__create_execution_context()).traverse_single(default) def _execute_text(self, statement, multiparams, params): parameters = self.__distill_params(multiparams, params) @@ -848,7 +847,7 @@ class Connection(Connectable): return context.result() def __create_execution_context(self, **kwargs): - return self.__engine.dialect.create_execution_context(connection=self, **kwargs) + return self.engine.dialect.create_execution_context(connection=self, **kwargs) def __execute_raw(self, context): if context.executemany: @@ -857,9 +856,9 @@ class Connection(Connectable): self._cursor_execute(context.cursor, context.statement, context.parameters[0], context=context) def _cursor_execute(self, cursor, statement, parameters, context=None): - if self.__engine._should_log_info: - self.__engine.logger.info(statement) - self.__engine.logger.info(repr(parameters)) + if self.engine._should_log_info: + self.engine.logger.info(statement) + self.engine.logger.info(repr(parameters)) try: self.dialect.do_execute(cursor, statement, parameters, context=context) except Exception, e: @@ -873,9 +872,9 @@ class Connection(Connectable): raise exceptions.DBAPIError.instance(statement, parameters, e) def _cursor_executemany(self, cursor, statement, parameters, context=None): - if self.__engine._should_log_info: - self.__engine.logger.info(statement) - self.__engine.logger.info(repr(parameters)) + if self.engine._should_log_info: + self.engine.logger.info(statement) + self.engine.logger.info(repr(parameters)) try: self.dialect.do_executemany(cursor, statement, parameters, context=context) except Exception, e: @@ -900,20 +899,20 @@ class Connection(Connectable): def create(self, entity, **kwargs): """Create a Table or Index given an appropriate Schema object.""" - return self.__engine.create(entity, connection=self, **kwargs) + return self.engine.create(entity, connection=self, **kwargs) def drop(self, entity, **kwargs): """Drop a Table or Index given an appropriate Schema object.""" - return self.__engine.drop(entity, connection=self, **kwargs) + return self.engine.drop(entity, connection=self, **kwargs) def reflecttable(self, table, include_columns=None): """Reflect the columns in the given string table name from the database.""" - return self.__engine.reflecttable(table, self, include_columns) + return self.engine.reflecttable(table, self, include_columns) def default_schema_name(self): - return self.__engine.dialect.get_default_schema_name(self) + return self.engine.dialect.get_default_schema_name(self) def run_callable(self, callable_): return callable_(self) diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index c98519ffe8..771ca06f9a 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -136,15 +136,32 @@ class DefaultExecutionContext(base.ExecutionContext): self.dialect = dialect self._connection = self.root_connection = connection self.compiled = compiled - self._postfetch_cols = util.Set() self.engine = connection.engine if compiled is not None: + # compiled clauseelement. process bind params, process table defaults, + # track collections used by ResultProxy to target and process results + + self.processors = dict([ + (key, value) for key, value in + [( + compiled.bind_names[bindparam], + bindparam.bind_processor(self.dialect) + ) for bindparam in compiled.bind_names] + if value is not None + ]) + self.typemap = compiled.typemap self.column_labels = compiled.column_labels - self.statement = unicode(compiled) + + if not dialect.supports_unicode_statements: + self.statement = unicode(compiled).encode(self.dialect.encoding) + else: + self.statement = unicode(compiled) + self.isinsert = compiled.isinsert self.isupdate = compiled.isupdate + if not parameters: self.compiled_parameters = [compiled.construct_params()] self.executemany = False @@ -152,20 +169,26 @@ class DefaultExecutionContext(base.ExecutionContext): self.compiled_parameters = [compiled.construct_params(m) for m in parameters] self.executemany = len(parameters) > 1 + self.cursor = self.create_cursor() + self.__process_defaults() + self.parameters = self.__convert_compiled_params(self.compiled_parameters) + elif statement is not None: + # plain text statement. self.typemap = self.column_labels = None self.parameters = self.__encode_param_keys(parameters) self.executemany = len(parameters) > 1 - self.statement = statement + if not dialect.supports_unicode_statements: + self.statement = statement.encode(self.dialect.encoding) + else: + self.statement = statement self.isinsert = self.isupdate = False + self.cursor = self.create_cursor() else: + # no statement. used for standalone ColumnDefault execution. self.statement = None self.isinsert = self.isupdate = self.executemany = False - - if self.statement is not None and not dialect.supports_unicode_statements: - self.statement = self.statement.encode(self.dialect.encoding) - - self.cursor = self.create_cursor() + self.cursor = self.create_cursor() connection = property(lambda s:s._connection._branch()) @@ -190,13 +213,40 @@ class DefaultExecutionContext(base.ExecutionContext): return dict([(k.encode(self.dialect.encoding), d[k]) for k in d]) return [proc(d) for d in params] or [{}] - def __convert_compiled_params(self, parameters): - processors = parameters[0].get_processors() + def __convert_compiled_params(self, compiled_parameters): + """convert the dictionary of bind parameter values into a dict or list + to be sent to the DBAPI's execute() or executemany() method. + """ + + processors = self.processors + parameters = [] if self.dialect.positional: - parameters = [p.get_raw_list(processors) for p in parameters] + for compiled_params in compiled_parameters: + param = [] + for key in self.compiled.positiontup: + if key in processors: + param.append(processors[key](compiled_params[key])) + else: + param.append(compiled_params[key]) + parameters.append(param) else: encode = not self.dialect.supports_unicode_statements - parameters = [p.get_raw_dict(processors, encode_keys=encode) for p in parameters] + for compiled_params in compiled_parameters: + param = {} + if encode: + encoding = self.dialect.encoding + for key in compiled_params: + if key in processors: + param[key.encode(encoding)] = processors[key](compiled_params[key]) + else: + param[key.encode(encoding)] = compiled_params[key] + else: + for key in compiled_params: + if key in processors: + param[key] = processors[key](compiled_params[key]) + else: + param[key] = compiled_params[key] + parameters.append(param) return parameters def is_select(self): @@ -220,8 +270,7 @@ class DefaultExecutionContext(base.ExecutionContext): return AUTOCOMMIT_REGEXP.match(self.statement) def pre_exec(self): - self._process_defaults() - self.parameters = self.__convert_compiled_params(self.compiled_parameters) + pass def post_exec(self): pass @@ -251,7 +300,7 @@ class DefaultExecutionContext(base.ExecutionContext): return self._last_updated_params def lastrow_has_defaults(self): - return len(self._postfetch_cols) + return hasattr(self, '_postfetch_cols') and len(self._postfetch_cols) def postfetch_cols(self): return self._postfetch_cols @@ -282,7 +331,7 @@ class DefaultExecutionContext(base.ExecutionContext): inputsizes[key.encode(self.dialect.encoding)] = dbtype self.cursor.setinputsizes(**inputsizes) - def _process_defaults(self): + def __process_defaults(self): """generate default values for compiled insert/update statements, and generate last_inserted_ids() collection.""" @@ -292,6 +341,9 @@ class DefaultExecutionContext(base.ExecutionContext): drunner = self.dialect.defaultrunner(self) params = self.compiled_parameters for param in params: + # assign each dict of params to self.compiled_parameters; + # this allows user-defined default generators to access the full + # set of bind params for the row self.compiled_parameters = param for c in self.compiled.prefetch: if self.isinsert: @@ -299,32 +351,26 @@ class DefaultExecutionContext(base.ExecutionContext): else: val = drunner.get_column_onupdate(c) if val is not None: - param.set_value(c.key, val) + param[c.key] = val self.compiled_parameters = params else: compiled_parameters = self.compiled_parameters[0] drunner = self.dialect.defaultrunner(self) - if self.isinsert: - self._last_inserted_ids = [] + 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: - compiled_parameters.set_value(c.key, val) + compiled_parameters[c.key] = val if self.isinsert: - processors = compiled_parameters.get_processors() - for c in self.compiled.statement.table.primary_key: - if c.key in compiled_parameters: - self._last_inserted_ids.append(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_ids = [compiled_parameters.get(c.key, None) for c in self.compiled.statement.table.primary_key] self._last_inserted_params = compiled_parameters else: self._last_updated_params = compiled_parameters + + self._postfetch_cols = self.compiled.postfetch diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 94ef04300d..73c8321fc7 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1167,8 +1167,8 @@ class Mapper(object): v = self.get_attr_by_column(obj, c, False) if v is NO_ATTRIBUTE: continue - elif v != params.get_original(c.key): - self.set_attr_by_column(obj, c, params.get_original(c.key)) + elif v != params[c.key]: + self.set_attr_by_column(obj, c, params[c.key]) if deferred_props: deferred_load(obj, props=deferred_props) diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 43b6fb15b5..fa4ac5a9f4 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -182,27 +182,18 @@ class DefaultCompiler(engine.Compiled, visitors.ClauseVisitor): return None def construct_params(self, params=None): - """Return a sql.util.ClauseParameters object. + """return a dictionary of bind parameter keys and values""" - Combines the given bind parameter dictionary (string keys to object values) - with the _BindParamClause objects stored within this Compiled object - to produce a ClauseParameters structure, representing the bind arguments - for a single statement execution, or one element of an executemany execution. - """ - - d = sql_util.ClauseParameters(self.dialect, self.positiontup) - - pd = params or {} - - bind_names = self.bind_names - for key, bind in self.binds.iteritems(): - # the following is an inlined ClauseParameters.set_parameter() - name = bind_names[bind] - d._binds[name] = [bind, name, pd.get(key, bind.value)] - return d + if params: + pd = {} + for key, bindparam in self.binds.iteritems(): + name = self.bind_names[bindparam] + pd[name] = params.get(key, bindparam.value) + return pd + else: + return dict([(self.bind_names[bindparam], bindparam.value) for bindparam in self.bind_names]) - params = property(lambda self:self.construct_params(), doc="""Return the `ClauseParameters` corresponding to this compiled object. - A shortcut for `construct_params()`.""") + params = property(lambda self:self.construct_params(), doc="""return a dictionary of bind parameter keys and values""") def default_from(self): """Called when a SELECT statement has no froms, and no FROM clause is to be appended. diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 48996fe7bd..8876f42baa 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -3,107 +3,6 @@ from sqlalchemy.sql import expression, visitors """Utility functions that build upon SQL and Schema constructs.""" -class ClauseParameters(object): - """Represent a dictionary/iterator of bind parameter key names/values. - - Tracks the original [sqlalchemy.sql#_BindParamClause] objects as well as the - keys/position of each parameter, and can return parameters as a - dictionary or a list. Will process parameter values according to - the ``TypeEngine`` objects present in the ``_BindParamClause`` instances. - """ - - __slots__ = 'dialect', '_binds', 'positional' - - def __init__(self, dialect, positional=None): - self.dialect = dialect - self._binds = {} - if positional is None: - self.positional = [] - else: - self.positional = positional - - def get_parameter(self, key): - return self._binds[key] - - def set_parameter(self, bindparam, value, name): - self._binds[name] = [bindparam, name, value] - - def get_original(self, key): - return self._binds[key][2] - - def get_type(self, key): - return self._binds[key][0].type - - def get_processors(self): - """return a dictionary of bind 'processing' functions""" - return dict([ - (key, value) for key, value in - [( - key, - self._binds[key][0].bind_processor(self.dialect) - ) for key in self._binds] - if value is not None - ]) - - def get_processed(self, key, processors): - if key in processors: - return processors[key](self._binds[key][2]) - else: - return self._binds[key][2] - - def keys(self): - return self._binds.keys() - - def __iter__(self): - return iter(self.keys()) - - def __getitem__(self, key): - (bind, name, value) = self._binds[key] - processor = bind.bind_processor(self.dialect) - if processor is not None: - return processor(value) - else: - return value - - def __contains__(self, key): - return key in self._binds - - def set_value(self, key, value): - self._binds[key][2] = value - - def get_original_dict(self): - return dict([(name, value) for (b, name, value) in self._binds.values()]) - - def get_raw_list(self, processors): - binds, res = self._binds, [] - for key in self.positional: - if key in processors: - res.append(processors[key](binds[key][2])) - else: - res.append(binds[key][2]) - return res - - def get_raw_dict(self, processors, encode_keys=False): - binds, res = self._binds, {} - if encode_keys: - encoding = self.dialect.encoding - for key in self.keys(): - if key in processors: - res[key.encode(encoding)] = processors[key](binds[key][2]) - else: - res[key.encode(encoding)] = binds[key][2] - else: - for key in self.keys(): - if key in processors: - res[key] = processors[key](binds[key][2]) - else: - res[key] = binds[key][2] - return res - - def __repr__(self): - return self.__class__.__name__ + ":" + repr(self.get_original_dict()) - - class TableCollection(object): def __init__(self, tables=None): diff --git a/test/profiling/zoomark.py b/test/profiling/zoomark.py index 58033ad976..6eb313b429 100644 --- a/test/profiling/zoomark.py +++ b/test/profiling/zoomark.py @@ -50,7 +50,7 @@ class ZooMarkTest(testing.AssertMixin): metadata.create_all() @testing.supported('postgres') - @profiling.profiled('populate', call_range=(3360, 4400), always=True) + @profiling.profiled('populate', call_range=(2990, 4400), always=True) def test_1a_populate(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] @@ -118,7 +118,7 @@ class ZooMarkTest(testing.AssertMixin): MotherID=bai_yun) @testing.supported('postgres') - @profiling.profiled('insert', call_range=(180, 250), always=True) + @profiling.profiled('insert', call_range=(160, 250), always=True) def test_2_insert(self): Animal = metadata.tables['Animal'] i = Animal.insert() @@ -126,7 +126,7 @@ class ZooMarkTest(testing.AssertMixin): tick = i.execute(Species='Tick', Name='Tick %d' % x, Legs=8) @testing.supported('postgres') - @profiling.profiled('properties', call_range=(3060, 3430), always=True) + @profiling.profiled('properties', call_range=(3030, 3430), always=True) def test_3_properties(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] @@ -149,7 +149,7 @@ class ZooMarkTest(testing.AssertMixin): ticks = fullobject(Animal.select(Animal.c.Species=='Tick')) @testing.supported('postgres') - @profiling.profiled('expressions', call_range=(11450, 13200), always=True) + @profiling.profiled('expressions', call_range=(11350, 13200), always=True) def test_4_expressions(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] @@ -203,7 +203,7 @@ class ZooMarkTest(testing.AssertMixin): assert len(fulltable(Animal.select(func.date_part('day', Animal.c.LastEscape) == 21))) == 1 @testing.supported('postgres') - @profiling.profiled('aggregates', call_range=(1020, 1270), always=True) + @profiling.profiled('aggregates', call_range=(1000, 1270), always=True) def test_5_aggregates(self): Animal = metadata.tables['Animal'] Zoo = metadata.tables['Zoo'] @@ -245,7 +245,7 @@ class ZooMarkTest(testing.AssertMixin): legs.sort() @testing.supported('postgres') - @profiling.profiled('editing', call_range=(1300, 1390), always=True) + @profiling.profiled('editing', call_range=(1280, 1390), always=True) def test_6_editing(self): Zoo = metadata.tables['Zoo'] @@ -274,7 +274,7 @@ class ZooMarkTest(testing.AssertMixin): assert SDZ['Founded'] == datetime.date(1935, 9, 13) @testing.supported('postgres') - @profiling.profiled('multiview', call_range=(2850, 3155), always=True) + @profiling.profiled('multiview', call_range=(2820, 3155), always=True) def test_7_multiview(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] diff --git a/test/sql/query.py b/test/sql/query.py index 67384073cb..c4a3e9e0da 100644 --- a/test/sql/query.py +++ b/test/sql/query.py @@ -123,7 +123,8 @@ class QueryTest(PersistTest): continue try: table.create() - assert insert_values(table, values) == assertvalues, repr(values) + " " + repr(assertvalues) + i = insert_values(table, values) + assert i == assertvalues, repr(i) + " " + repr(assertvalues) finally: table.drop() diff --git a/test/sql/select.py b/test/sql/select.py index 56bf1d92ca..ace4557027 100644 --- a/test/sql/select.py +++ b/test/sql/select.py @@ -614,7 +614,7 @@ WHERE mytable.myid = myothertable.otherid) AS t2view WHERE t2view.mytable_myid = self.assert_compile( text("select * from foo where lala=:bar and hoho=:whee", bindparams=[bindparam('bar',4), bindparam('whee',7)]), "select * from foo where lala=? and hoho=?", - checkparams=[4, 7], + checkparams={'bar':4, 'whee':7}, dialect=dialect ) @@ -921,17 +921,19 @@ EXISTS (select yay from foo where boo = lar)", self.assert_compile(stmt, expected_positional_stmt, dialect=sqlite.dialect()) nonpositional = stmt.compile() positional = stmt.compile(dialect=sqlite.dialect()) - assert positional.get_params().get_raw_list({}) == expected_default_params_list - assert nonpositional.get_params(**test_param_dict).get_raw_dict({}) == expected_test_params_dict, "expected :%s got %s" % (str(expected_test_params_dict), str(nonpositional.get_params(**test_param_dict).get_raw_dict())) - assert positional.get_params(**test_param_dict).get_raw_list({}) == expected_test_params_list + pp = positional.get_params() + assert [pp[k] for k in positional.positiontup] == expected_default_params_list + assert nonpositional.get_params(**test_param_dict) == expected_test_params_dict, "expected :%s got %s" % (str(expected_test_params_dict), str(nonpositional.get_params(**test_param_dict).get_raw_dict())) + pp = positional.get_params(**test_param_dict) + assert [pp[k] for k in positional.positiontup] == expected_test_params_list # check that params() doesnt modify original statement s = select([table1], or_(table1.c.myid==bindparam('myid'), table2.c.otherid==bindparam('myotherid'))) s2 = s.params({'myid':8, 'myotherid':7}) s3 = s2.params({'myid':9}) - assert s.compile().params.get_original_dict() == {'myid':None, 'myotherid':None} - assert s2.compile().params.get_original_dict() == {'myid':8, 'myotherid':7} - assert s3.compile().params.get_original_dict() == {'myid':9, 'myotherid':7} + assert s.compile().params == {'myid':None, 'myotherid':None} + assert s2.compile().params == {'myid':8, 'myotherid':7} + assert s3.compile().params == {'myid':9, 'myotherid':7} # check that conflicts with "unique" params are caught diff --git a/test/testlib/testing.py b/test/testlib/testing.py index 3a2c38ce61..a1fb174b73 100644 --- a/test/testlib/testing.py +++ b/test/testlib/testing.py @@ -195,8 +195,7 @@ class ExecutionContextWrapper(object): if params is not None and not isinstance(params, list): params = [params] - from sqlalchemy.sql.util import ClauseParameters - parameters = [p.get_original_dict() for p in ctx.compiled_parameters] + parameters = ctx.compiled_parameters query = self.convert_statement(query) testdata.unittest.assert_(statement == query and (params is None or params == parameters), "Testing for query '%s' params %s, received '%s' with params %s" % (query, repr(params), statement, repr(parameters))) @@ -255,10 +254,7 @@ class SQLCompileTest(PersistTest): self.assert_(cc == result, "\n'" + cc + "'\n does not match \n'" + result + "'") if checkparams is not None: - if isinstance(checkparams, list): - self.assert_(c.params.get_raw_list({}) == checkparams, "params dont match ") - else: - self.assert_(c.params.get_original_dict() == checkparams, "params dont match" + repr(c.params)) + self.assert_(c.params == checkparams, "params dont match" + repr(c.params)) class AssertMixin(PersistTest): """given a list-based structure of keys/properties which represent information within an object structure, and -- 2.47.3