From a9b62055bfa61c11e9fe0b2984437e2c3e32bf0e Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 9 Mar 2020 17:12:35 -0400 Subject: [PATCH] Try to measure new style caching in the ORM, take two Supercedes: If78fbb557c6f2cae637799c3fec2cbc5ac248aaf Trying to see if by making the cache key memoized, we still can have the older "identity" form of caching which is the cheapest of all, at the same time as the newer "cache key each time" version that is not nearly as cheap; but still much cheaper than no caching at all. Also needed is a per-execution update of _keymap when we invoke from a cached select, so that Column objects that are anonymous or otherwise adapted will match up. this is analogous to the adaption of bound parameters from the cache key. Adds test coverage for the keymap / construct_params() changes related to caching. Also hones performance to a large extent for statement construction and cache key generation. Also includes a new memoized attribute approach that vastly simplifies the previous approach of "group_expirable_memoized_property" and finally integrates cleanly with _clone(), _generate(), etc. no more hardcoding of attributes is needed, as well as that most _reset_memoization() calls are no longer needed as the reset is inherent in a _generate() call; this also has dramatic performance improvements. Change-Id: I95c560ffcbfa30b26644999412fb6a385125f663 --- examples/performance/short_selects.py | 27 +- lib/sqlalchemy/engine/base.py | 20 +- lib/sqlalchemy/engine/default.py | 25 +- lib/sqlalchemy/engine/result.py | 42 +- lib/sqlalchemy/orm/instrumentation.py | 18 +- lib/sqlalchemy/orm/mapper.py | 73 ++- lib/sqlalchemy/orm/relationships.py | 7 +- lib/sqlalchemy/sql/annotation.py | 19 +- lib/sqlalchemy/sql/base.py | 18 +- lib/sqlalchemy/sql/coercions.py | 6 +- lib/sqlalchemy/sql/compiler.py | 70 ++- lib/sqlalchemy/sql/crud.py | 6 +- lib/sqlalchemy/sql/dml.py | 23 + lib/sqlalchemy/sql/elements.py | 73 ++- lib/sqlalchemy/sql/functions.py | 5 +- lib/sqlalchemy/sql/schema.py | 2 +- lib/sqlalchemy/sql/selectable.py | 132 +++-- lib/sqlalchemy/sql/traversals.py | 60 ++- lib/sqlalchemy/sql/type_api.py | 11 + lib/sqlalchemy/sql/util.py | 1 - lib/sqlalchemy/sql/visitors.py | 11 + lib/sqlalchemy/util/__init__.py | 4 +- lib/sqlalchemy/util/langhelpers.py | 71 ++- test/aaa_profiling/test_memusage.py | 15 +- test/aaa_profiling/test_misc.py | 12 +- test/ext/test_baked.py | 85 ++++ test/profiles.txt | 662 +++++++++++++------------- test/sql/test_compare.py | 46 ++ test/sql/test_compiler.py | 112 ++++- test/sql/test_external_traversal.py | 2 +- test/sql/test_functions.py | 5 +- test/sql/test_resultset.py | 107 ++++- test/sql/test_selectable.py | 8 +- 33 files changed, 1214 insertions(+), 564 deletions(-) diff --git a/examples/performance/short_selects.py b/examples/performance/short_selects.py index 376f18f02d..db8ab8789c 100644 --- a/examples/performance/short_selects.py +++ b/examples/performance/short_selects.py @@ -13,6 +13,7 @@ from sqlalchemy import select from sqlalchemy import String from sqlalchemy.ext import baked from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.future import select as future_select from sqlalchemy.orm import deferred from sqlalchemy.orm import Session from . import Profiler @@ -116,6 +117,20 @@ def test_core_new_stmt_each_time(n): tuple(row) +@Profiler.profile +def test_core_new_stmt_each_time_compiled_cache(n): + """test core, creating a new statement each time, but using the cache.""" + + compiled_cache = {} + with engine.connect().execution_options( + compiled_cache=compiled_cache + ) as conn: + for id_ in random.sample(ids, n): + stmt = select([Customer.__table__]).where(Customer.id == id_) + row = conn.execute(stmt).first() + tuple(row) + + @Profiler.profile def test_core_reuse_stmt(n): """test core, reusing the same statement (but recompiling each time).""" @@ -132,8 +147,8 @@ def test_core_reuse_stmt(n): def test_core_reuse_stmt_compiled_cache(n): """test core, reusing the same statement + compiled cache.""" - compiled_cache = {} stmt = select([Customer.__table__]).where(Customer.id == bindparam("id")) + compiled_cache = {} with engine.connect().execution_options( compiled_cache=compiled_cache ) as conn: @@ -142,5 +157,15 @@ def test_core_reuse_stmt_compiled_cache(n): tuple(row) +@Profiler.profile +def test_core_just_statement_construct_plus_cache_key(n): + for i in range(n): + stmt = future_select(Customer.__table__).where( + Customer.id == bindparam("id") + ) + + stmt._generate_cache_key() + + if __name__ == "__main__": Profiler.main() diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 4ed3b9af7a..34a4f04a96 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1000,7 +1000,8 @@ class Connection(Connectable): tuple or scalar positional parameters. """ - if isinstance(object_, util.string_types[0]): + + if isinstance(object_, util.string_types): util.warn_deprecated_20( "Passing a string to Connection.execute() is " "deprecated and will be removed in version 2.0. Use the " @@ -1098,26 +1099,33 @@ class Connection(Connectable): keys = [] dialect = self.dialect + if "compiled_cache" in self._execution_options: + elem_cache_key, extracted_params = elem._generate_cache_key() key = ( dialect, - elem, + elem_cache_key, tuple(sorted(keys)), bool(self._schema_translate_map), len(distilled_params) > 1, ) - compiled_sql = self._execution_options["compiled_cache"].get(key) + cache = self._execution_options["compiled_cache"] + compiled_sql = cache.get(key) + if compiled_sql is None: compiled_sql = elem.compile( dialect=dialect, + cache_key=(elem_cache_key, extracted_params), column_keys=keys, inline=len(distilled_params) > 1, schema_translate_map=self._schema_translate_map, linting=self.dialect.compiler_linting | compiler.WARN_LINTING, ) - self._execution_options["compiled_cache"][key] = compiled_sql + cache[key] = compiled_sql + else: + extracted_params = None compiled_sql = elem.compile( dialect=dialect, column_keys=keys, @@ -1133,6 +1141,8 @@ class Connection(Connectable): distilled_params, compiled_sql, distilled_params, + elem, + extracted_params, ) if self._has_events or self.engine._has_events: self.dispatch.after_execute(self, elem, multiparams, params, ret) @@ -1156,6 +1166,8 @@ class Connection(Connectable): parameters, compiled, parameters, + None, + None, ) if self._has_events or self.engine._has_events: self.dispatch.after_execute( diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index c44f07538e..af61be034f 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -750,7 +750,14 @@ class DefaultExecutionContext(interfaces.ExecutionContext): @classmethod def _init_compiled( - cls, dialect, connection, dbapi_connection, compiled, parameters + cls, + dialect, + connection, + dbapi_connection, + compiled, + parameters, + invoked_statement, + extracted_parameters, ): """Initialize execution context for a Compiled construct.""" @@ -758,7 +765,8 @@ class DefaultExecutionContext(interfaces.ExecutionContext): self.root_connection = connection self._dbapi_connection = dbapi_connection self.dialect = connection.dialect - + self.extracted_parameters = extracted_parameters + self.invoked_statement = invoked_statement self.compiled = compiled # this should be caught in the engine before @@ -778,7 +786,6 @@ class DefaultExecutionContext(interfaces.ExecutionContext): compiled._textual_ordered_columns, compiled._loose_column_name_matching, ) - self.isinsert = compiled.isinsert self.isupdate = compiled.isupdate self.isdelete = compiled.isdelete @@ -792,10 +799,18 @@ class DefaultExecutionContext(interfaces.ExecutionContext): ) if not parameters: - self.compiled_parameters = [compiled.construct_params()] + self.compiled_parameters = [ + compiled.construct_params( + extracted_parameters=extracted_parameters + ) + ] else: self.compiled_parameters = [ - compiled.construct_params(m, _group_number=grp) + compiled.construct_params( + m, + _group_number=grp, + extracted_parameters=extracted_parameters, + ) for grp, m in enumerate(parameters) ] diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index ac033a5aec..986edd617a 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -114,6 +114,44 @@ class CursorResultMetaData(ResultMetaData): "keys", ) + def _adapt_to_context(self, context): + """When using a cached result metadata against a new context, + we need to rewrite the _keymap so that it has the specific + Column objects in the new context inside of it. this accommodates + for select() constructs that contain anonymized columns and + are cached. + + """ + if not context.compiled._result_columns: + return self + + compiled_statement = context.compiled.statement + invoked_statement = context.invoked_statement + + # same statement was invoked as the one we cached against, + # return self + if compiled_statement is invoked_statement: + return self + + # make a copy and add the columns from the invoked statement + # to the result map. + md = self.__class__.__new__(self.__class__) + + md._keymap = self._keymap.copy() + + # match up new columns positionally to the result columns + for existing, new in zip( + context.compiled._result_columns, + invoked_statement._exported_columns_iterator(), + ): + md._keymap[new] = md._keymap[existing[RM_NAME]] + + md.case_sensitive = self.case_sensitive + md.matched_on_name = self.matched_on_name + md._processors = self._processors + md.keys = self.keys + return md + def __init__(self, parent, cursor_description): context = parent.context dialect = context.dialect @@ -1107,7 +1145,9 @@ class BaseResult(object): if strat.cursor_description is not None: if self.context.compiled: if self.context.compiled._cached_metadata: - self._metadata = self.context.compiled._cached_metadata + cached_md = self.context.compiled._cached_metadata + self._metadata = cached_md._adapt_to_context(self.context) + else: self._metadata = ( self.context.compiled._cached_metadata diff --git a/lib/sqlalchemy/orm/instrumentation.py b/lib/sqlalchemy/orm/instrumentation.py index 785f540859..432bff7d41 100644 --- a/lib/sqlalchemy/orm/instrumentation.py +++ b/lib/sqlalchemy/orm/instrumentation.py @@ -36,12 +36,10 @@ from . import exc from . import interfaces from . import state from .. import util +from ..util import HasMemoized -_memoized_key_collection = util.group_expirable_memoized_property() - - -class ClassManager(dict): +class ClassManager(HasMemoized, dict): """tracks state information at the class level.""" MANAGER_ATTR = base.DEFAULT_MANAGER_ATTR @@ -122,17 +120,17 @@ class ClassManager(dict): def is_mapped(self): return "mapper" in self.__dict__ - @_memoized_key_collection + @HasMemoized.memoized_attribute def _all_key_set(self): return frozenset(self) - @_memoized_key_collection + @HasMemoized.memoized_attribute def _collection_impl_keys(self): return frozenset( [attr.key for attr in self.values() if attr.impl.collection] ) - @_memoized_key_collection + @HasMemoized.memoized_attribute def _scalar_loader_impls(self): return frozenset( [ @@ -142,7 +140,7 @@ class ClassManager(dict): ] ) - @_memoized_key_collection + @HasMemoized.memoized_attribute def _loader_impls(self): return frozenset([attr.impl for attr in self.values()]) @@ -261,7 +259,7 @@ class ClassManager(dict): else: self.local_attrs[key] = inst self.install_descriptor(key, inst) - _memoized_key_collection.expire_instance(self) + self._reset_memoizations() self[key] = inst for cls in self.class_.__subclasses__(): @@ -291,7 +289,7 @@ class ClassManager(dict): else: del self.local_attrs[key] self.uninstall_descriptor(key) - _memoized_key_collection.expire_instance(self) + self._reset_memoizations() del self[key] for cls in self.class_.__subclasses__(): manager = manager_of_class(cls) diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index cd974190b4..f4e20afdfd 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -52,13 +52,12 @@ from ..sql import operators from ..sql import roles from ..sql import util as sql_util from ..sql import visitors +from ..util import HasMemoized _mapper_registry = weakref.WeakKeyDictionary() _already_compiling = False -_memoized_configured_property = util.group_expirable_memoized_property() - # a constant returned by _get_attr_by_column to indicate # this mapper is not handling an attribute for a particular @@ -1635,14 +1634,14 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): _validate_polymorphic_identity = None - @_memoized_configured_property + @HasMemoized.memoized_attribute def _version_id_prop(self): if self.version_id_col is not None: return self._columntoproperty[self.version_id_col] else: return None - @_memoized_configured_property + @HasMemoized.memoized_attribute def _acceptable_polymorphic_identities(self): identities = set() @@ -1655,7 +1654,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return identities - @_memoized_configured_property + @HasMemoized.memoized_attribute def _prop_set(self): return frozenset(self._props.values()) @@ -1708,7 +1707,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): col = m.local_table.corresponding_column(prop.columns[0]) if col is not None: for m2 in path: - m2.persist_selectable._reset_exported() + m2.persist_selectable._refresh_for_new_column(col) col = self.persist_selectable.corresponding_column( prop.columns[0] ) @@ -1859,7 +1858,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): # mapped table, this corresponds to adding a # column after the fact to the local table. # [ticket:1523] - self.persist_selectable._reset_exported() + self.persist_selectable._refresh_for_new_column(mc) mc = self.persist_selectable.corresponding_column(c) if mc is None: raise sa_exc.ArgumentError( @@ -1929,7 +1928,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): def _expire_memoizations(self): for mapper in self.iterate_to_root(): - _memoized_configured_property.expire_instance(mapper) + mapper._reset_memoizations() @property def _log_desc(self): @@ -2078,7 +2077,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return from_obj - @_memoized_configured_property + @HasMemoized.memoized_attribute def _single_table_criterion(self): if self.single and self.inherits and self.polymorphic_on is not None: return self.polymorphic_on._annotate({"parentmapper": self}).in_( @@ -2087,7 +2086,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): else: return None - @_memoized_configured_property + @HasMemoized.memoized_attribute def _with_polymorphic_mappers(self): if Mapper._new_mappers: configure_mappers() @@ -2095,7 +2094,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return [] return self._mappers_from_spec(*self.with_polymorphic) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _with_polymorphic_selectable(self): if not self.with_polymorphic: return self.persist_selectable @@ -2114,7 +2113,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): """ - @_memoized_configured_property + @HasMemoized.memoized_attribute def _insert_cols_evaluating_none(self): return dict( ( @@ -2126,7 +2125,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): for table, columns in self._cols_by_table.items() ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _insert_cols_as_none(self): return dict( ( @@ -2143,7 +2142,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): for table, columns in self._cols_by_table.items() ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _propkey_to_col(self): return dict( ( @@ -2155,14 +2154,14 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): for table, columns in self._cols_by_table.items() ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _pk_keys_by_table(self): return dict( (table, frozenset([col.key for col in pks])) for table, pks in self._pks_by_table.items() ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _pk_attr_keys_by_table(self): return dict( ( @@ -2172,7 +2171,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): for table, pks in self._pks_by_table.items() ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _server_default_cols(self): return dict( ( @@ -2188,7 +2187,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): for table, columns in self._cols_by_table.items() ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _server_default_plus_onupdate_propkeys(self): result = set() @@ -2202,7 +2201,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return result - @_memoized_configured_property + @HasMemoized.memoized_attribute def _server_onupdate_default_cols(self): return dict( ( @@ -2258,7 +2257,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): else: return mappers, self._selectable_from_mappers(mappers, innerjoin) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _polymorphic_properties(self): return list( self._iterate_polymorphic_properties( @@ -2294,7 +2293,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): continue yield c - @_memoized_configured_property + @HasMemoized.memoized_attribute def attrs(self): """A namespace of all :class:`.MapperProperty` objects associated this mapper. @@ -2332,7 +2331,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): configure_mappers() return util.ImmutableProperties(self._props) - @_memoized_configured_property + @HasMemoized.memoized_attribute def all_orm_descriptors(self): """A namespace of all :class:`.InspectionAttr` attributes associated with the mapped class. @@ -2379,7 +2378,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): dict(self.class_manager._all_sqla_attributes()) ) - @_memoized_configured_property + @HasMemoized.memoized_attribute @util.preload_module("sqlalchemy.orm.descriptor_props") def synonyms(self): """Return a namespace of all :class:`.SynonymProperty` @@ -2395,7 +2394,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return self._filter_properties(descriptor_props.SynonymProperty) - @_memoized_configured_property + @HasMemoized.memoized_attribute def column_attrs(self): """Return a namespace of all :class:`.ColumnProperty` properties maintained by this :class:`.Mapper`. @@ -2409,7 +2408,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return self._filter_properties(properties.ColumnProperty) @util.preload_module("sqlalchemy.orm.relationships") - @_memoized_configured_property + @HasMemoized.memoized_attribute def relationships(self): """A namespace of all :class:`.RelationshipProperty` properties maintained by this :class:`.Mapper`. @@ -2436,7 +2435,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): util.preloaded.orm_relationships.RelationshipProperty ) - @_memoized_configured_property + @HasMemoized.memoized_attribute @util.preload_module("sqlalchemy.orm.descriptor_props") def composites(self): """Return a namespace of all :class:`.CompositeProperty` @@ -2461,7 +2460,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): ) ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _get_clause(self): """create a "get clause" based on the primary key. this is used by query.get() and many-to-one lazyloads to load this item @@ -2477,7 +2476,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): util.column_dict(params), ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _equivalent_columns(self): """Create a map of all equivalent columns, based on the determination of column pairs that are equated to @@ -2610,7 +2609,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): yield m m = m.inherits - @_memoized_configured_property + @HasMemoized.memoized_attribute def self_and_descendants(self): """The collection including this mapper and all descendant mappers. @@ -2737,7 +2736,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): ) return identity_key[1] - @_memoized_configured_property + @HasMemoized.memoized_attribute def _persistent_sortkey_fn(self): key_fns = [col.type.sort_key_function for col in self.primary_key] @@ -2756,25 +2755,25 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return key - @_memoized_configured_property + @HasMemoized.memoized_attribute def _identity_key_props(self): return [self._columntoproperty[col] for col in self.primary_key] - @_memoized_configured_property + @HasMemoized.memoized_attribute def _all_pk_props(self): collection = set() for table in self.tables: collection.update(self._pks_by_table[table]) return collection - @_memoized_configured_property + @HasMemoized.memoized_attribute def _should_undefer_in_wildcard(self): cols = set(self.primary_key) if self.polymorphic_on is not None: cols.add(self.polymorphic_on) return cols - @_memoized_configured_property + @HasMemoized.memoized_attribute def _primary_key_propkeys(self): return {prop.key for prop in self._all_pk_props} @@ -2993,7 +2992,7 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): return q, enable_opt, disable_opt - @_memoized_configured_property + @HasMemoized.memoized_attribute def _subclass_load_via_in_mapper(self): return self._subclass_load_via_in(self) @@ -3074,11 +3073,11 @@ class Mapper(sql_base.HasCacheKey, InspectionAttr): ) ) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _compiled_cache(self): return util.LRUCache(self._compiled_cache_size) - @_memoized_configured_property + @HasMemoized.memoized_attribute def _sorted_tables(self): table_to_mapper = {} diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py index 227543485f..8b7a4b549d 100644 --- a/lib/sqlalchemy/orm/relationships.py +++ b/lib/sqlalchemy/orm/relationships.py @@ -1412,13 +1412,14 @@ class RelationshipProperty(StrategizedProperty): if self.property.direction == MANYTOONE: state = attributes.instance_state(other) - def state_bindparam(x, state, col): + def state_bindparam(local_col, state, remote_col): dict_ = state.dict return sql.bindparam( - x, + local_col.key, + type_=local_col.type, unique=True, callable_=self.property._get_attr_w_warn_on_none( - self.property.mapper, state, dict_, col + self.property.mapper, state, dict_, remote_col ), ) diff --git a/lib/sqlalchemy/sql/annotation.py b/lib/sqlalchemy/sql/annotation.py index 7984dc7ea3..d895e730c1 100644 --- a/lib/sqlalchemy/sql/annotation.py +++ b/lib/sqlalchemy/sql/annotation.py @@ -13,6 +13,7 @@ associations. from . import operators from .base import HasCacheKey +from .traversals import anon_map from .visitors import InternalTraversal from .. import util @@ -20,12 +21,13 @@ from .. import util class SupportsAnnotations(object): @util.memoized_property def _annotations_cache_key(self): + anon_map_ = anon_map() return ( "_annotations", tuple( ( key, - value._gen_cache_key(None, []) + value._gen_cache_key(anon_map_, []) if isinstance(value, HasCacheKey) else value, ) @@ -38,7 +40,7 @@ class SupportsCloneAnnotations(SupportsAnnotations): _annotations = util.immutabledict() _clone_annotations_traverse_internals = [ - ("_annotations_cache_key", InternalTraversal.dp_plain_obj) + ("_annotations", InternalTraversal.dp_annotations_key) ] def _annotate(self, values): @@ -133,6 +135,8 @@ class Annotated(object): """ + _is_column_operators = False + def __new__(cls, *args): if not args: # clone constructor @@ -200,7 +204,7 @@ class Annotated(object): return self._hash def __eq__(self, other): - if isinstance(self.__element, operators.ColumnOperators): + if self._is_column_operators: return self.__element.__class__.__eq__(self, other) else: return hash(other) == hash(self) @@ -208,7 +212,9 @@ class Annotated(object): # hard-generate Annotated subclasses. this technique # is used instead of on-the-fly types (i.e. type.__new__()) -# so that the resulting objects are pickleable. +# so that the resulting objects are pickleable; additionally, other +# decisions can be made up front about the type of object being annotated +# just once per class rather than per-instance. annotated_classes = {} @@ -310,8 +316,11 @@ def _new_annotation_type(cls, base_cls): if "_traverse_internals" in cls.__dict__: anno_cls._traverse_internals = list(cls._traverse_internals) + [ - ("_annotations_cache_key", InternalTraversal.dp_plain_obj) + ("_annotations", InternalTraversal.dp_annotations_key) ] + + anno_cls._is_column_operators = issubclass(cls, operators.ColumnOperators) + return anno_cls diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py index 974ca6ddb4..eea4003f24 100644 --- a/lib/sqlalchemy/sql/base.py +++ b/lib/sqlalchemy/sql/base.py @@ -19,6 +19,7 @@ from .visitors import ClauseVisitor from .visitors import InternalTraversal from .. import exc from .. import util +from ..util import HasMemoized if util.TYPE_CHECKING: from types import ModuleType @@ -58,18 +59,6 @@ class SingletonConstant(Immutable): cls._singleton = obj -class HasMemoized(object): - def _reset_memoizations(self): - self._memoized_property.expire_instance(self) - - def _reset_exported(self): - self._memoized_property.expire_instance(self) - - def _copy_internals(self, **kw): - super(HasMemoized, self)._copy_internals(**kw) - self._reset_memoizations() - - def _from_objects(*elements): return itertools.chain.from_iterable( [element._from_objects for element in elements] @@ -461,13 +450,14 @@ class CompileState(object): self.statement = statement -class Generative(object): +class Generative(HasMemoized): """Provide a method-chaining pattern in conjunction with the @_generative decorator.""" def _generate(self): + skip = self._memoized_keys s = self.__class__.__new__(self.__class__) - s.__dict__ = self.__dict__.copy() + s.__dict__ = {k: v for k, v in self.__dict__.items() if k not in skip} return s diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index 679d9c6e9b..e605b486b4 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -320,11 +320,7 @@ class BinaryElementImpl( self._raise_for_expected(element, err=err) def _post_coercion(self, resolved, expr, **kw): - if ( - isinstance(resolved, (elements.Grouping, elements.BindParameter)) - and resolved.type._isnull - and not expr.type._isnull - ): + if resolved.type._isnull and not expr.type._isnull: resolved = resolved._with_binary_element_type(expr.type) return resolved diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 87ae5232e7..799fca2f58 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -470,7 +470,7 @@ class Compiled(object): return self.string or "" - def construct_params(self, params=None): + def construct_params(self, params=None, extracted_parameters=None): """Return the bind params for this compiled object. :param params: a dict of string/object pairs whose values will @@ -664,6 +664,7 @@ class SQLCompiler(Compiled): self, dialect, statement, + cache_key=None, column_keys=None, inline=False, linting=NO_LINTING, @@ -687,6 +688,8 @@ class SQLCompiler(Compiled): """ self.column_keys = column_keys + self.cache_key = cache_key + # compile INSERT/UPDATE defaults/sequences inlined (no pre- # execute) self.inline = inline or getattr(statement, "_inline", False) @@ -818,9 +821,38 @@ class SQLCompiler(Compiled): def sql_compiler(self): return self - def construct_params(self, params=None, _group_number=None, _check=True): + def construct_params( + self, + params=None, + _group_number=None, + _check=True, + extracted_parameters=None, + ): """return a dictionary of bind parameter keys and values""" + if extracted_parameters: + # related the bound parameters collected in the original cache key + # to those collected in the incoming cache key. They will not have + # matching names but they will line up positionally in the same + # way. The parameters present in self.bind_names may be clones of + # these original cache key params in the case of DML but the .key + # will be guaranteed to match. + try: + orig_extracted = self.cache_key[1] + except TypeError as err: + util.raise_( + exc.CompileError( + "This compiled object has no original cache key; " + "can't pass extracted_parameters to construct_params" + ), + replace_context=err, + ) + resolved_extracted = dict( + zip([b.key for b in orig_extracted], extracted_parameters) + ) + else: + resolved_extracted = None + if params: pd = {} for bindparam in self.bind_names: @@ -844,11 +876,18 @@ class SQLCompiler(Compiled): % bindparam.key, code="cd3x", ) - - elif bindparam.callable: - pd[name] = bindparam.effective_value else: - pd[name] = bindparam.value + if resolved_extracted: + value_param = resolved_extracted.get( + bindparam.key, bindparam + ) + else: + value_param = bindparam + + if bindparam.callable: + pd[name] = value_param.effective_value + else: + pd[name] = value_param.value return pd else: pd = {} @@ -868,10 +907,19 @@ class SQLCompiler(Compiled): code="cd3x", ) + if resolved_extracted: + value_param = resolved_extracted.get( + bindparam.key, bindparam + ) + else: + value_param = bindparam + if bindparam.callable: - pd[self.bind_names[bindparam]] = bindparam.effective_value + pd[ + self.bind_names[bindparam] + ] = value_param.effective_value else: - pd[self.bind_names[bindparam]] = bindparam.value + pd[self.bind_names[bindparam]] = value_param.value return pd @property @@ -2144,7 +2192,9 @@ class SQLCompiler(Compiled): assert False recur_cols = [ c - for c in util.unique_list(col_source.inner_columns) + for c in util.unique_list( + col_source._exported_columns_iterator() + ) if c is not None ] @@ -3375,7 +3425,7 @@ class DDLCompiler(Compiled): def type_compiler(self): return self.dialect.type_compiler - def construct_params(self, params=None): + def construct_params(self, params=None, extracted_parameters=None): return None def visit_ddl(self, ddl, **kwargs): diff --git a/lib/sqlalchemy/sql/crud.py b/lib/sqlalchemy/sql/crud.py index 2827a58173..114dbec9eb 100644 --- a/lib/sqlalchemy/sql/crud.py +++ b/lib/sqlalchemy/sql/crud.py @@ -16,7 +16,6 @@ from . import coercions from . import dml from . import elements from . import roles -from .elements import ClauseElement from .. import exc from .. import util @@ -198,11 +197,8 @@ def _handle_values_anonymous_param(compiler, col, value, name, **kw): if value.type._isnull: # either unique parameter, or other bound parameters that were # passed in directly - # clone using base ClauseElement to retain unique key - value = ClauseElement._clone(value) - # set type to that of the column unconditionally - value.type = col.type + value = value._with_binary_element_type(col.type) return value._compiler_dispatch(compiler, **kw) diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index 5c75e068fa..cbcf54d1c6 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -14,6 +14,7 @@ from . import coercions from . import roles from .base import _from_objects from .base import _generative +from .base import ColumnCollection from .base import CompileState from .base import DialectKWArgs from .base import Executable @@ -364,6 +365,28 @@ class UpdateBase( """ self._returning = cols + def _exported_columns_iterator(self): + """Return the RETURNING columns as a sequence for this statement. + + .. versionadded:: 1.4 + + """ + + return self._returning or () + + @property + def exported_columns(self): + """Return the RETURNING columns as a column collection for this + statement. + + .. versionadded:: 1.4 + + """ + # TODO: no coverage here + return ColumnCollection( + (c.key, c) for c in self._exported_columns_iterator() + ).as_immutable() + @_generative def with_hint(self, text, selectable=None, dialect_name="*"): """Add a table hint for a single table to this diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 2b994c513d..57d41b06fb 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -175,7 +175,7 @@ def not_(clause): @inspection._self_inspects class ClauseElement( - roles.SQLRole, SupportsWrappingAnnotations, HasCacheKey, Traversible + roles.SQLRole, SupportsWrappingAnnotations, HasCacheKey, Traversible, ): """Base class for elements of a programmatically constructed SQL expression. @@ -215,10 +215,9 @@ class ClauseElement( the _copy_internals() method. """ + skip = self._memoized_keys c = self.__class__.__new__(self.__class__) - c.__dict__ = self.__dict__.copy() - ClauseElement._cloned_set._reset(c) - ColumnElement.comparator._reset(c) + c.__dict__ = {k: v for k, v in self.__dict__.items() if k not in skip} # this is a marker that helps to "equate" clauses to each other # when a Select returns its list of FROM clauses. the cloning @@ -250,7 +249,7 @@ class ClauseElement( """ return self.__class__ - @util.memoized_property + @HasMemoized.memoized_attribute def _cloned_set(self): """Return the set consisting all cloned ancestors of this ClauseElement. @@ -276,6 +275,7 @@ class ClauseElement( def __getstate__(self): d = self.__dict__.copy() d.pop("_is_clone_of", None) + d.pop("_generate_cache_key", None) return d def _execute_on_connection(self, connection, multiparams, params): @@ -740,15 +740,7 @@ class ColumnElement( def type(self): return type_api.NULLTYPE - def _with_binary_element_type(self, type_): - cloned = self._clone() - cloned._copy_internals( - clone=lambda element: element._with_binary_element_type(type_) - ) - cloned.type = type_ - return cloned - - @util.memoized_property + @HasMemoized.memoized_attribute def comparator(self): try: comparator_factory = self.type.comparator_factory @@ -1022,6 +1014,7 @@ class BindParameter(roles.InElementRole, ColumnElement): _is_crud = False _expanding_in_types = () _is_bind_parameter = True + _key_is_anon = False def __init__( self, @@ -1273,9 +1266,6 @@ class BindParameter(roles.InElementRole, ColumnElement): """ - if isinstance(key, ColumnClause): - type_ = key.type - key = key.key if required is NO_ARG: required = value is NO_ARG and callable_ is None if value is NO_ARG: @@ -1297,8 +1287,12 @@ class BindParameter(roles.InElementRole, ColumnElement): else "param", ) ) + self._key_is_anon = True + elif key: + self.key = key else: - self.key = key or _anonymous_label("%%(%d param)s" % id(self)) + self.key = _anonymous_label("%%(%d param)s" % id(self)) + self._key_is_anon = True # identifying key that won't change across # clones, used to identify the bind's logical @@ -1366,6 +1360,11 @@ class BindParameter(roles.InElementRole, ColumnElement): else: return self.value + def _with_binary_element_type(self, type_): + c = ClauseElement._clone(self) + c.type = type_ + return c + def _clone(self): c = ClauseElement._clone(self) if self.unique: @@ -1390,7 +1389,7 @@ class BindParameter(roles.InElementRole, ColumnElement): id_, self.__class__, self.type._static_cache_key, - traversals._resolve_name_for_compare(self, self.key, anon_map), + self.key % anon_map if self._key_is_anon else self.key, ) def _convert_to_unique(self): @@ -2790,7 +2789,7 @@ class Cast(WrapsColumnExpression, ColumnElement): return self.clause -class TypeCoerce(HasMemoized, WrapsColumnExpression, ColumnElement): +class TypeCoerce(WrapsColumnExpression, ColumnElement): """Represent a Python-side type-coercion wrapper. :class:`.TypeCoerce` supplies the :func:`.expression.type_coerce` @@ -2815,8 +2814,6 @@ class TypeCoerce(HasMemoized, WrapsColumnExpression, ColumnElement): ("type", InternalTraversal.dp_type), ] - _memoized_property = util.group_expirable_memoized_property() - def __init__(self, expression, type_): r"""Associate a SQL expression with a particular type, without rendering ``CAST``. @@ -2889,7 +2886,7 @@ class TypeCoerce(HasMemoized, WrapsColumnExpression, ColumnElement): def _from_objects(self): return self.clause._from_objects - @_memoized_property + @HasMemoized.memoized_attribute def typed_expression(self): if isinstance(self.clause, BindParameter): bp = self.clause._clone() @@ -3435,7 +3432,7 @@ class BinaryExpression(ColumnElement): # refer to BinaryExpression directly and pass strings if isinstance(operator, util.string_types): operator = operators.custom_op(operator) - self._orig = (hash(left), hash(right)) + self._orig = (left.__hash__(), right.__hash__()) self.left = left.self_group(against=operator) self.right = right.self_group(against=operator) self.operator = operator @@ -3450,7 +3447,7 @@ class BinaryExpression(ColumnElement): def __bool__(self): if self.operator in (operator.eq, operator.ne): - return self.operator(self._orig[0], self._orig[1]) + return self.operator(*self._orig) else: raise TypeError("Boolean value of this clause is not defined") @@ -3546,6 +3543,9 @@ class Grouping(GroupedElement, ColumnElement): self.element = element self.type = getattr(element, "type", type_api.NULLTYPE) + def _with_binary_element_type(self, type_): + return Grouping(self.element._with_binary_element_type(type_)) + @util.memoized_property def _is_implicitly_boolean(self): return self.element._is_implicitly_boolean @@ -4015,7 +4015,7 @@ class FunctionFilter(ColumnElement): ) -class Label(HasMemoized, roles.LabeledColumnExprRole, ColumnElement): +class Label(roles.LabeledColumnExprRole, ColumnElement): """Represents a column label (AS). Represent a label, as typically applied to any column-level @@ -4031,8 +4031,6 @@ class Label(HasMemoized, roles.LabeledColumnExprRole, ColumnElement): ("_element", InternalTraversal.dp_clauseelement), ] - _memoized_property = util.group_expirable_memoized_property() - def __init__(self, name, element, type_=None): """Return a :class:`Label` object for the given :class:`.ColumnElement`. @@ -4075,7 +4073,7 @@ class Label(HasMemoized, roles.LabeledColumnExprRole, ColumnElement): def _is_implicitly_boolean(self): return self.element._is_implicitly_boolean - @_memoized_property + @HasMemoized.memoized_attribute def _allow_label_resolve(self): return self.element._allow_label_resolve @@ -4089,7 +4087,7 @@ class Label(HasMemoized, roles.LabeledColumnExprRole, ColumnElement): self._type or getattr(self._element, "type", None) ) - @_memoized_property + @HasMemoized.memoized_attribute def element(self): return self._element.self_group(against=operators.as_) @@ -4116,7 +4114,6 @@ class Label(HasMemoized, roles.LabeledColumnExprRole, ColumnElement): return self.element.foreign_keys def _copy_internals(self, clone=_clone, anonymize_labels=False, **kw): - self._reset_memoizations() self._element = clone(self._element, **kw) if anonymize_labels: self.name = self._resolve_label = _anonymous_label( @@ -4194,8 +4191,6 @@ class ColumnClause( _is_multiparam_column = False - _memoized_property = util.group_expirable_memoized_property() - def __init__(self, text, type_=None, is_literal=False, _selectable=None): """Produce a :class:`.ColumnClause` object. @@ -4312,7 +4307,7 @@ class ColumnClause( else: return [] - @_memoized_property + @HasMemoized.memoized_attribute def _from_objects(self): t = self.table if t is not None: @@ -4327,18 +4322,18 @@ class ColumnClause( else: return self.name.encode("ascii", "backslashreplace") - @_memoized_property + @HasMemoized.memoized_attribute def _key_label(self): if self.key != self.name: return self._gen_label(self.key) else: return self._label - @_memoized_property + @HasMemoized.memoized_attribute def _label(self): return self._gen_label(self.name) - @_memoized_property + @HasMemoized.memoized_attribute def _render_label_in_columns_clause(self): return self.table is not None @@ -4599,14 +4594,14 @@ def _corresponding_column_or_error(fromclause, column, require_embedded=False): class AnnotatedColumnElement(Annotated): def __init__(self, element, values): Annotated.__init__(self, element, values) - ColumnElement.comparator._reset(self) + self.__dict__.pop("comparator", None) for attr in ("name", "key", "table"): if self.__dict__.get(attr, False) is None: self.__dict__.pop(attr) def _with_annotations(self, values): clone = super(AnnotatedColumnElement, self)._with_annotations(values) - ColumnElement.comparator._reset(clone) + clone.__dict__.pop("comparator", None) return clone @util.memoized_property diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index 6004f6b51c..7973871f33 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -17,6 +17,7 @@ from . import sqltypes from . import util as sqlutil from .base import ColumnCollection from .base import Executable +from .base import HasMemoized from .elements import _type_from_args from .elements import BinaryExpression from .elements import BindParameter @@ -85,8 +86,6 @@ class FunctionElement(Executable, ColumnElement, FromClause): _has_args = False - _memoized_property = FromClause._memoized_property - def __init__(self, *clauses, **kwargs): r"""Construct a :class:`.FunctionElement`. @@ -141,7 +140,7 @@ class FunctionElement(Executable, ColumnElement, FromClause): col = self.label(None) return ColumnCollection(columns=[(col.key, col)]) - @_memoized_property + @HasMemoized.memoized_attribute def clauses(self): """Return the underlying :class:`.ClauseList` which contains the arguments for this :class:`.FunctionElement`. diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 02c14d7513..5c6b1f3c6e 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -1412,7 +1412,7 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): "assign a non-blank .name before adding to a Table." ) - Column._memoized_property.expire_instance(self) + self._reset_memoizations() if self.key is None: self.key = self.name diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 4eab60801a..e39d61fdbb 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -106,31 +106,33 @@ class ReturnsRows(roles.ReturnsRowsRole, ClauseElement): def selectable(self): raise NotImplementedError() + def _exported_columns_iterator(self): + """An iterator of column objects that represents the "exported" + columns of this :class:`.ReturnsRows`. -class Selectable(ReturnsRows): - """mark a class as being selectable. - - """ + This is the same set of columns as are returned by + :meth:`.ReturnsRows.exported_columns` except they are returned + as a simple iterator or sequence, rather than as a + :class:`.ColumnCollection` namespace. - __visit_name__ = "selectable" - - is_selectable = True + Subclasses should re-implement this method to bypass the interim + creation of the :class:`.ColumnCollection` if appropriate. - @property - def selectable(self): - return self + """ + return iter(self.exported_columns) @property def exported_columns(self): """A :class:`.ColumnCollection` that represents the "exported" - columns of this :class:`.Selectable`. + columns of this :class:`.ReturnsRows`. The "exported" columns represent the collection of :class:`.ColumnElement` expressions that are rendered by this SQL - construct. There are two primary varieties which are the + construct. There are primary varieties which are the "FROM clause columns" of a FROM clause, such as a table, join, - or subquery, and the "SELECTed columns", which are the columns in - the "columns clause" of a SELECT statement. + or subquery, the "SELECTed columns", which are the columns in + the "columns clause" of a SELECT statement, and the RETURNING + columns in a DML statement.. .. versionadded:: 1.4 @@ -143,6 +145,20 @@ class Selectable(ReturnsRows): raise NotImplementedError() + +class Selectable(ReturnsRows): + """mark a class as being selectable. + + """ + + __visit_name__ = "selectable" + + is_selectable = True + + @property + def selectable(self): + return self + def _refresh_for_new_column(self, column): raise NotImplementedError() @@ -312,7 +328,7 @@ class HasSuffixes(object): ) -class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): +class FromClause(roles.AnonymizedFromClauseRole, Selectable): """Represent an element that can be used within the ``FROM`` clause of a ``SELECT`` statement. @@ -350,8 +366,6 @@ class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): _use_schema_map = False - _memoized_property = util.group_expirable_memoized_property(["_columns"]) - @util.deprecated( "1.1", message="The :meth:`.FromClause.count` method is deprecated, " @@ -571,7 +585,7 @@ class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): """ return self.columns - @_memoized_property + @util.memoized_property def columns(self): """A named-based collection of :class:`.ColumnElement` objects maintained by this :class:`.FromClause`. @@ -589,7 +603,7 @@ class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): self._populate_column_collection() return self._columns.as_immutable() - @_memoized_property + @util.memoized_property def primary_key(self): """Return the collection of Column objects which comprise the primary key of this FromClause.""" @@ -598,7 +612,7 @@ class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): self._populate_column_collection() return self.primary_key - @_memoized_property + @util.memoized_property def foreign_keys(self): """Return the collection of ForeignKey objects which this FromClause references.""" @@ -607,6 +621,23 @@ class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): self._populate_column_collection() return self.foreign_keys + def _reset_column_collection(self): + """Reset the attributes linked to the FromClause.c attribute. + + This collection is separate from all the other memoized things + as it has shown to be sensitive to being cleared out in situations + where enclosing code, typically in a replacement traversal scenario, + has already established strong relationships + with the exported columns. + + The collection is cleared for the case where a table is having a + column added to it as well as within a Join during copy internals. + + """ + + for key in ["_columns", "columns", "primary_key", "foreign_keys"]: + self.__dict__.pop(key, None) + c = property( attrgetter("columns"), doc="An alias for the :attr:`.columns` attribute.", @@ -659,7 +690,7 @@ class FromClause(HasMemoized, roles.AnonymizedFromClauseRole, Selectable): derivations. """ - self._reset_exported() + self._reset_column_collection() class Join(FromClause): @@ -1239,7 +1270,7 @@ class AliasedReturnsRows(NoInit, FromClause): # same object. don't reset exported .c. collections and other # memoized details if nothing changed if element is not self.element: - self._reset_exported() + self._reset_column_collection() self.element = element @property @@ -2141,7 +2172,6 @@ class SelectBase( roles.DMLSelectRole, roles.CompoundElementRole, roles.InElementRole, - HasMemoized, HasCTE, Executable, SupportsCloneAnnotations, @@ -2158,8 +2188,6 @@ class SelectBase( _is_select_statement = True - _memoized_property = util.group_expirable_memoized_property() - def _generate_fromclause_column_proxies(self, fromclause): # type: (FromClause) -> None raise NotImplementedError() @@ -2254,7 +2282,7 @@ class SelectBase( def outerjoin(self, *arg, **kw): return self._implicit_subquery.outerjoin(*arg, **kw) - @_memoized_property + @HasMemoized.memoized_attribute def _implicit_subquery(self): return self.subquery() @@ -2315,15 +2343,6 @@ class SelectBase( """ return Lateral._factory(self, name) - def _generate(self): - """Override the default _generate() method to also clear out - exported collections.""" - - s = self.__class__.__new__(self.__class__) - s.__dict__ = self.__dict__.copy() - s._reset_memoizations() - return s - @property def _from_objects(self): return [self] @@ -2431,6 +2450,9 @@ class SelectStatementGrouping(GroupedElement, SelectBase): def _generate_proxy_for_new_column(self, column, subquery): return self.element._generate_proxy_for_new_column(subquery) + def _exported_columns_iterator(self): + return self.element._exported_columns_iterator() + @property def selected_columns(self): """A :class:`.ColumnCollection` representing the columns that @@ -3046,6 +3068,9 @@ class CompoundSelect(HasCompileState, GenerativeSelect): for select in self.selects: select._refresh_for_new_column(column) + def _exported_columns_iterator(self): + return self.selects[0]._exported_columns_iterator() + @property def selected_columns(self): """A :class:`.ColumnCollection` representing the columns that @@ -3339,8 +3364,6 @@ class Select( _from_obj = () _auto_correlate = True - _memoized_property = SelectBase._memoized_property - _traverse_internals = ( [ ("_from_obj", InternalTraversal.dp_clauseelement_list), @@ -3400,8 +3423,7 @@ class Select( self = cls.__new__(cls) self._raw_columns = [ - coercions.expect(roles.ColumnsClauseRole, ent) - for ent in util.to_list(entities) + coercions.expect(roles.ColumnsClauseRole, ent) for ent in entities ] GenerativeSelect.__init__(self) @@ -3739,8 +3761,12 @@ class Select( """an iterator of all ColumnElement expressions which would be rendered into the columns clause of the resulting SELECT statement. + This method is legacy as of 1.4 and is superseded by the + :attr:`.Select.exported_columns` collection. + """ - return _select_iterables(self._raw_columns) + + return self._exported_columns_iterator() def is_derived_from(self, fromclause): if self in fromclause._cloned_set: @@ -3786,7 +3812,10 @@ class Select( clone=clone, omit_attrs=("_from_obj",), **kw ) - self._reset_memoizations() + # memoizations should be cleared here as of + # I95c560ffcbfa30b26644999412fb6a385125f663 , asserting this + # is the case for now. + self._assert_no_memoizations() def get_children(self, **kwargs): return list(set(self._iterate_from_elements())) + super( @@ -3809,7 +3838,10 @@ class Select( :class:`.Select` object. """ - self._reset_memoizations() + # memoizations should be cleared here as of + # I95c560ffcbfa30b26644999412fb6a385125f663 , asserting this + # is the case for now. + self._assert_no_memoizations() self._raw_columns = self._raw_columns + [ coercions.expect(roles.ColumnsClauseRole, column,) @@ -3861,7 +3893,7 @@ class Select( """ return self.with_only_columns( util.preloaded.sql_util.reduce_columns( - self.inner_columns, + self._exported_columns_iterator(), only_synonyms=only_synonyms, *(self._where_criteria + self._from_obj) ) @@ -3935,7 +3967,12 @@ class Select( being asked to select both from ``table1`` as well as itself. """ - self._reset_memoizations() + + # memoizations should be cleared here as of + # I95c560ffcbfa30b26644999412fb6a385125f663 , asserting this + # is the case for now. + self._assert_no_memoizations() + rc = [] for c in columns: c = coercions.expect(roles.ColumnsClauseRole, c,) @@ -4112,7 +4149,7 @@ class Select( coercions.expect(roles.FromClauseRole, f) for f in fromclauses ) - @_memoized_property + @HasMemoized.memoized_attribute def selected_columns(self): """A :class:`.ColumnCollection` representing the columns that this SELECT statement or similar construct returns in its result set. @@ -4167,6 +4204,9 @@ class Select( return ColumnCollection(collection).as_immutable() + def _exported_columns_iterator(self): + return _select_iterables(self._raw_columns) + def _ensure_disambiguated_names(self): if self._label_style is LABEL_STYLE_NONE: self = self._set_label_style(LABEL_STYLE_DISAMBIGUATE_ONLY) @@ -4558,7 +4598,7 @@ class TextualSelect(SelectBase): ] self.positional = positional - @SelectBase._memoized_property + @HasMemoized.memoized_attribute def selected_columns(self): """A :class:`.ColumnCollection` representing the columns that this SELECT statement or similar construct returns in its result set. diff --git a/lib/sqlalchemy/sql/traversals.py b/lib/sqlalchemy/sql/traversals.py index 1fcc2d0233..9ac6cda978 100644 --- a/lib/sqlalchemy/sql/traversals.py +++ b/lib/sqlalchemy/sql/traversals.py @@ -7,6 +7,7 @@ from .visitors import ExtendedInternalTraversal from .visitors import InternalTraversal from .. import util from ..inspection import inspect +from ..util import HasMemoized SKIP_TRAVERSE = util.symbol("skip_traverse") COMPARE_FAILED = False @@ -26,7 +27,7 @@ def compare(obj1, obj2, **kw): return strategy.compare(obj1, obj2, **kw) -class HasCacheKey(object): +class HasCacheKey(HasMemoized): _cache_key_traversal = NO_CACHE __slots__ = () @@ -105,6 +106,14 @@ class HasCacheKey(object): attrname, obj._gen_cache_key(anon_map, bindparams), ) + elif meth is InternalTraversal.dp_annotations_key: + # obj is here is the _annotations dict. however, + # we want to use the memoized cache key version of it. + # for Columns, this should be long lived. For select() + # statements, not so much, but they usually won't have + # annotations. + if obj: + result += self._annotations_cache_key elif meth is InternalTraversal.dp_clauseelement_list: if obj: result += ( @@ -130,6 +139,7 @@ class HasCacheKey(object): return result + @HasMemoized.memoized_instancemethod def _generate_cache_key(self): """return a cache key. @@ -161,6 +171,7 @@ class HasCacheKey(object): will return None, indicating no cache key is available. """ + bindparams = [] _anon_map = anon_map() @@ -178,6 +189,36 @@ class CacheKey(namedtuple("CacheKey", ["key", "bindparams"])): def __eq__(self, other): return self.key == other.key + def __str__(self): + stack = [self.key] + + output = [] + sentinel = object() + indent = -1 + while stack: + elem = stack.pop(0) + if elem is sentinel: + output.append((" " * (indent * 2)) + "),") + indent -= 1 + elif isinstance(elem, tuple): + if not elem: + output.append((" " * ((indent + 1) * 2)) + "()") + else: + indent += 1 + stack = list(elem) + [sentinel] + stack + output.append((" " * (indent * 2)) + "(") + else: + if isinstance(elem, HasCacheKey): + repr_ = "<%s object at %s>" % ( + type(elem).__name__, + hex(id(elem)), + ) + else: + repr_ = repr(elem) + output.append((" " * (indent * 2)) + " " + repr_ + ", ") + + return "CacheKey(key=%s)" % ("\n".join(output),) + def _clone(element, **kw): return element._clone() @@ -189,6 +230,8 @@ class _CacheKey(ExtendedInternalTraversal): visit_has_cache_key = visit_clauseelement = CALL_GEN_CACHE_KEY visit_clauseelement_list = InternalTraversal.dp_clauseelement_list + visit_annotations_key = InternalTraversal.dp_annotations_key + visit_string = ( visit_boolean ) = visit_operator = visit_plain_obj = CACHE_IN_PLACE @@ -690,8 +733,8 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): fillvalue=(None, None), ): if not compare_annotations and ( - (left_attrname == "_annotations_cache_key") - or (right_attrname == "_annotations_cache_key") + (left_attrname == "_annotations") + or (right_attrname == "_annotations") ): continue @@ -827,6 +870,17 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): ): return left == right + def visit_annotations_key( + self, left_parent, left, right_parent, right, **kw + ): + if left and right: + return ( + left_parent._annotations_cache_key + == right_parent._annotations_cache_key + ) + else: + return left == right + def visit_plain_obj(self, left_parent, left, right_parent, right, **kw): return left == right diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index 38189ec9d5..e3929fac7f 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -1414,6 +1414,17 @@ class Variant(TypeDecorator): self.impl = base self.mapping = mapping + @util.memoized_property + def _static_cache_key(self): + # TODO: needs tests in test/sql/test_compare.py + return (self.__class__,) + ( + self.impl._static_cache_key, + tuple( + (key, self.mapping[key]._static_cache_key) + for key in sorted(self.mapping) + ), + ) + def coerce_compared_value(self, operator, value): result = self.impl.coerce_compared_value(operator, value) if result is self.impl: diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 8d185ce7d1..fae68da987 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -584,7 +584,6 @@ def splice_joins(left, right, stop_on=None): (right, prevright) = stack.pop() if isinstance(right, Join) and right is not stop_on: right = right._clone() - right._reset_exported() right.onclause = adapter.traverse(right.onclause) stack.append((right.left, right)) else: diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py index 4c1aab62fd..5504bf3d8c 100644 --- a/lib/sqlalchemy/sql/visitors.py +++ b/lib/sqlalchemy/sql/visitors.py @@ -331,6 +331,17 @@ class InternalTraversal(util.with_metaclass(_InternalTraversalType, object)): """ + dp_annotations_key = symbol("AK") + """Visit the _annotations_cache_key element. + + This is a dictionary of additional information about a ClauseElement + that modifies its role. It should be included when comparing or caching + objects, however generating this key is relatively expensive. Visitors + should check the "_annotations" dict for non-None first before creating + this key. + + """ + dp_plain_obj = symbol("PO") """Visit a plain python object. diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py index c0e290cb0e..695985a910 100644 --- a/lib/sqlalchemy/util/__init__.py +++ b/lib/sqlalchemy/util/__init__.py @@ -119,7 +119,7 @@ from .langhelpers import get_callable_argspec # noqa from .langhelpers import get_cls_kwargs # noqa from .langhelpers import get_func_kwargs # noqa from .langhelpers import getargspec_init # noqa -from .langhelpers import group_expirable_memoized_property # noqa +from .langhelpers import HasMemoized # noqa from .langhelpers import hybridmethod # noqa from .langhelpers import hybridproperty # noqa from .langhelpers import iterate_attributes # noqa @@ -134,8 +134,8 @@ from .langhelpers import NoneType # noqa from .langhelpers import only_once # noqa from .langhelpers import PluginLoader # noqa from .langhelpers import portable_instancemethod # noqa -from .langhelpers import preloaded # noqa from .langhelpers import preload_module # noqa +from .langhelpers import preloaded # noqa from .langhelpers import quoted_token_parser # noqa from .langhelpers import safe_reraise # noqa from .langhelpers import set_creation_order # noqa diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index 4744639815..7e99060288 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -924,27 +924,56 @@ def memoized_instancemethod(fn): return update_wrapper(oneshot, fn) -class group_expirable_memoized_property(object): - """A family of @memoized_properties that can be expired in tandem.""" - - def __init__(self, attributes=()): - self.attributes = [] - if attributes: - self.attributes.extend(attributes) - - def expire_instance(self, instance): - """Expire all memoized properties for *instance*.""" - stash = instance.__dict__ - for attribute in self.attributes: - stash.pop(attribute, None) - - def __call__(self, fn): - self.attributes.append(fn.__name__) - return memoized_property(fn) - - def method(self, fn): - self.attributes.append(fn.__name__) - return memoized_instancemethod(fn) +class HasMemoized(object): + """A class that maintains the names of memoized elements in a + collection for easy cache clearing, generative, etc. + + """ + + _memoized_keys = frozenset() + + def _reset_memoizations(self): + for elem in self._memoized_keys: + self.__dict__.pop(elem, None) + + def _assert_no_memoizations(self): + for elem in self._memoized_keys: + assert elem not in self.__dict__ + + class memoized_attribute(object): + """A read-only @property that is only evaluated once.""" + + def __init__(self, fget, doc=None): + self.fget = fget + self.__doc__ = doc or fget.__doc__ + self.__name__ = fget.__name__ + + def __get__(self, obj, cls): + if obj is None: + return self + obj.__dict__[self.__name__] = result = self.fget(obj) + obj._memoized_keys |= {self.__name__} + return result + + @classmethod + def memoized_instancemethod(cls, fn): + """Decorate a method memoize its return value. + + """ + + def oneshot(self, *args, **kw): + result = fn(self, *args, **kw) + + def memo(*a, **kw): + return result + + memo.__name__ = fn.__name__ + memo.__doc__ = fn.__doc__ + self.__dict__[fn.__name__] = memo + self._memoized_keys |= {fn.__name__} + return result + + return update_wrapper(oneshot, fn) class MemoizedSlots(object): diff --git a/test/aaa_profiling/test_memusage.py b/test/aaa_profiling/test_memusage.py index 8ea59ac3be..ad4db4545e 100644 --- a/test/aaa_profiling/test_memusage.py +++ b/test/aaa_profiling/test_memusage.py @@ -1276,8 +1276,9 @@ class CycleTest(_fixtures.FixtureTest): s = Session() - # cycles here are due to ClauseElement._cloned_set - @assert_cycles(3) + # cycles here are due to ClauseElement._cloned_set, others + # as of cache key + @assert_cycles(4) def go(): s.query(User).join(User.addresses).all() @@ -1291,8 +1292,9 @@ class CycleTest(_fixtures.FixtureTest): def generate(): s.query(User).options(joinedload(User.addresses)).all() - # cycles here are due to ClauseElement._cloned_set and Load.context - @assert_cycles(28) + # cycles here are due to ClauseElement._cloned_set and Load.context, + # others as of cache key + @assert_cycles(29) def go(): generate() @@ -1310,8 +1312,9 @@ class CycleTest(_fixtures.FixtureTest): def test_plain_join_select(self): users, addresses = self.tables("users", "addresses") - # cycles here are due to ClauseElement._cloned_set - @assert_cycles(6) + # cycles here are due to ClauseElement._cloned_set, others + # as of cache key + @assert_cycles(7) def go(): s = select([users]).select_from(users.join(addresses)) state = s._compile_state_factory(s, None) diff --git a/test/aaa_profiling/test_misc.py b/test/aaa_profiling/test_misc.py index 8fd9e742bc..32ab23f5e8 100644 --- a/test/aaa_profiling/test_misc.py +++ b/test/aaa_profiling/test_misc.py @@ -106,7 +106,17 @@ class CacheKeyTest(fixtures.TestBase): ] @profiling.function_call_count(variance=0.15, warmup=2) - def test_statement_one(self, stmt_fixture_one): + def test_statement_key_is_cached(self, stmt_fixture_one): + current_key = None + for stmt in stmt_fixture_one: + key = stmt._generate_cache_key() + if current_key: + eq_(key, current_key) + else: + current_key = key + + @profiling.function_call_count(variance=0.15, warmup=0) + def test_statement_key_is_not_cached(self, stmt_fixture_one): current_key = None for stmt in stmt_fixture_one: key = stmt._generate_cache_key() diff --git a/test/ext/test_baked.py b/test/ext/test_baked.py index faf0ec5332..9906339c2b 100644 --- a/test/ext/test_baked.py +++ b/test/ext/test_baked.py @@ -1036,6 +1036,36 @@ class LazyLoaderTest(testing.AssertsCompiledSQL, BakedTest): mapper(Dingaling, self.tables.dingalings) return User, Address, Dingaling + def _o2m_threelevel_fixture(self, lazy="select", **kw): + Order = self.classes.Order + User = self.classes.User + Address = self.classes.Address + Dingaling = self.classes.Dingaling + + mapper( + Order, self.tables.orders, properties={"user": relationship(User)} + ) + + mapper( + User, + self.tables.users, + properties={ + "addresses": relationship( + Address, + order_by=self.tables.addresses.c.id, + lazy=lazy, + **kw + ) + }, + ) + mapper( + Address, + self.tables.addresses, + properties={"dingalings": relationship(Dingaling, lazy=lazy)}, + ) + mapper(Dingaling, self.tables.dingalings) + return Order, User, Address, Dingaling + def _m2o_fixture(self): User = self.classes.User Address = self.classes.Address @@ -1048,6 +1078,61 @@ class LazyLoaderTest(testing.AssertsCompiledSQL, BakedTest): ) return User, Address + def test_same_lazyload_multiple_paths(self): + """this is an initial test that requires the presence of + the ResultMetaData._adapt_to_context method. + + Both queries emit a lazyload against User.addresses that then + includes a subqueryload against Address.dingalings. + + The subqueryload produces an adapted query that has anonymized + columns. for these to be locatable in the result, the columns in + the adapted query have to match up to the result map, which is not + the case if the statement is pulled from the cache. + + The query is done in two different ways so that one lazyload will not + have a state.load_path on User, and the other one will. this means + there will be two different baked queries that both produce the same + Core SELECT statement. Using logical cache keys in Core, rather than + based on identity, means two different BakedContext objects will use + the same Core context. For this reason, at result fetch time the + ResultMetaData._adapt_to_context step is required so that the ORM can + still locate the columns. + + This will all be done differently with direct ORM results, however this + same issue that ResultMetaData has to be adapted to the live statement + will exist indepndently of baked queries. More statement-level caching + tests need to be added which test with complex statements that include + anonymous columns. + + """ + Order, User, Address, Dingaling = self._o2m_threelevel_fixture() + + sess = Session() + from sqlalchemy.orm import joinedload + + o1 = ( + sess.query(Order) + .options( + joinedload(Order.user) + .lazyload(User.addresses) + .subqueryload(Address.dingalings) + ) + .filter(Order.id == 2) + .first() + ) + assert o1.user.addresses[0].dingalings + + sess.expire_all() + + u1 = ( + sess.query(User) + .options(lazyload(User.addresses).subqueryload(Address.dingalings)) + .filter(User.id == 9) + .first() + ) + assert u1.addresses[0].dingalings + def test_no_cache_for_event(self, modify_query_fixture): m1 = modify_query_fixture(False) diff --git a/test/profiles.txt b/test/profiles.txt index bceab386b2..9133d63011 100644 --- a/test/profiles.txt +++ b/test/profiles.txt @@ -13,145 +13,159 @@ # TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mssql_pyodbc_dbapiunicode_cextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mssql_pyodbc_dbapiunicode_nocextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_dbapiunicode_cextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_dbapiunicode_nocextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_pymysql_dbapiunicode_cextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_pymysql_dbapiunicode_nocextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_dbapiunicode_cextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_cextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_cextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 62 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mssql_pyodbc_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mssql_pyodbc_dbapiunicode_nocextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_nocextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_pymysql_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_pymysql_dbapiunicode_nocextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_oracle_cx_oracle_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mssql_pyodbc_dbapiunicode_cextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mssql_pyodbc_dbapiunicode_nocextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_dbapiunicode_cextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_mysqldb_dbapiunicode_nocextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_pymysql_dbapiunicode_cextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_pymysql_dbapiunicode_nocextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_dbapiunicode_cextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_cextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_cextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 59 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mssql_pyodbc_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mssql_pyodbc_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_pymysql_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_pymysql_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_oracle_cx_oracle_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 64 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_select -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mssql_pyodbc_dbapiunicode_cextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mssql_pyodbc_dbapiunicode_nocextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_dbapiunicode_cextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_dbapiunicode_nocextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_pymysql_dbapiunicode_cextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_pymysql_dbapiunicode_nocextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_dbapiunicode_cextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_cextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_cextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 159 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mssql_pyodbc_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mssql_pyodbc_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_mysqldb_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_mysqldb_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_pymysql_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_pymysql_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_oracle_cx_oracle_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_cextensions 174 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 174 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mssql_pyodbc_dbapiunicode_cextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mssql_pyodbc_dbapiunicode_nocextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_dbapiunicode_cextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_mysqldb_dbapiunicode_nocextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_pymysql_dbapiunicode_cextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_pymysql_dbapiunicode_nocextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_dbapiunicode_cextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_cextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_cextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 155 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mssql_pyodbc_dbapiunicode_cextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mssql_pyodbc_dbapiunicode_nocextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_mysqldb_dbapiunicode_cextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_mysqldb_dbapiunicode_nocextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_pymysql_dbapiunicode_cextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_pymysql_dbapiunicode_nocextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_oracle_cx_oracle_dbapiunicode_cextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_cextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_cextensions 170 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 170 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_select_labels -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mssql_pyodbc_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mssql_pyodbc_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_mysqldb_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_mysqldb_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_pymysql_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_pymysql_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mssql_pyodbc_dbapiunicode_cextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mssql_pyodbc_dbapiunicode_nocextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_mysqldb_dbapiunicode_cextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_mysqldb_dbapiunicode_nocextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_pymysql_dbapiunicode_cextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_pymysql_dbapiunicode_nocextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_oracle_cx_oracle_dbapiunicode_cextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_cextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_cextensions 197 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 197 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mssql_pyodbc_dbapiunicode_cextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mssql_pyodbc_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_mysqldb_dbapiunicode_cextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_mysqldb_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_pymysql_dbapiunicode_cextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_pymysql_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_dbapiunicode_cextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_cextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_cextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 173 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mssql_pyodbc_dbapiunicode_cextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mssql_pyodbc_dbapiunicode_nocextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_mysqldb_dbapiunicode_cextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_mysqldb_dbapiunicode_nocextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_pymysql_dbapiunicode_cextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_pymysql_dbapiunicode_nocextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_oracle_cx_oracle_dbapiunicode_cextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_cextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_cextensions 188 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 188 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_update -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mssql_pyodbc_dbapiunicode_cextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mssql_pyodbc_dbapiunicode_nocextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_dbapiunicode_cextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_dbapiunicode_nocextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_pymysql_dbapiunicode_cextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_pymysql_dbapiunicode_nocextensions 67 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_dbapiunicode_cextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_cextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_cextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 69 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mssql_pyodbc_dbapiunicode_cextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mssql_pyodbc_dbapiunicode_nocextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_cextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_nocextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_pymysql_dbapiunicode_cextensions 70 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_pymysql_dbapiunicode_nocextensions 70 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_oracle_cx_oracle_dbapiunicode_cextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_cextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_cextensions 72 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 72 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mssql_pyodbc_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mssql_pyodbc_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_mysqldb_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_pymysql_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_pymysql_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_cextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 64 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mssql_pyodbc_dbapiunicode_cextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mssql_pyodbc_dbapiunicode_nocextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_cextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_nocextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_pymysql_dbapiunicode_cextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_pymysql_dbapiunicode_nocextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_oracle_cx_oracle_dbapiunicode_cextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_cextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_cextensions 67 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 67 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mssql_pyodbc_dbapiunicode_cextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mssql_pyodbc_dbapiunicode_nocextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_dbapiunicode_cextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_dbapiunicode_nocextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_pymysql_dbapiunicode_cextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_pymysql_dbapiunicode_nocextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_dbapiunicode_cextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_cextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_cextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 154 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mssql_pyodbc_dbapiunicode_cextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mssql_pyodbc_dbapiunicode_nocextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_mysqldb_dbapiunicode_cextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_mysqldb_dbapiunicode_nocextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_pymysql_dbapiunicode_cextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_pymysql_dbapiunicode_nocextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_oracle_cx_oracle_dbapiunicode_cextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_cextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_cextensions 162 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 162 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mssql_pyodbc_dbapiunicode_cextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mssql_pyodbc_dbapiunicode_nocextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_dbapiunicode_cextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_mysqldb_dbapiunicode_nocextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_pymysql_dbapiunicode_cextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_pymysql_dbapiunicode_nocextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_dbapiunicode_cextensions 150 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 150 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_cextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_cextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 148 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mssql_pyodbc_dbapiunicode_cextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mssql_pyodbc_dbapiunicode_nocextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_mysqldb_dbapiunicode_cextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_mysqldb_dbapiunicode_nocextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_pymysql_dbapiunicode_cextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_pymysql_dbapiunicode_nocextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_oracle_cx_oracle_dbapiunicode_cextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_cextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_cextensions 154 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 154 + +# TEST: test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_cached + +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_cached 2.7_sqlite_pysqlite_dbapiunicode_cextensions 302 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_cached 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 302 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_cached 3.7_sqlite_pysqlite_dbapiunicode_cextensions 303 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_cached 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 303 + +# TEST: test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_not_cached + +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_not_cached 2.7_sqlite_pysqlite_dbapiunicode_cextensions 3702 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_not_cached 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 3702 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_not_cached 3.7_sqlite_pysqlite_dbapiunicode_cextensions 4292 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_key_is_not_cached 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 4292 # TEST: test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one -test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 2.7_sqlite_pysqlite_dbapiunicode_cextensions 4002 -test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 4002 -test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 3.7_sqlite_pysqlite_dbapiunicode_cextensions 4703 -test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 4703 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 2.7_sqlite_pysqlite_dbapiunicode_cextensions 302 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 302 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 3.7_sqlite_pysqlite_dbapiunicode_cextensions 303 +test.aaa_profiling.test_misc.CacheKeyTest.test_statement_one 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 303 # TEST: test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members @@ -162,66 +176,66 @@ test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_ # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 48505 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 64205 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 50405 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 64205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 47405 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 63105 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 49305 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 63105 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 48005 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 63705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 49905 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 63705 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46905 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 62605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48805 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 62605 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46905 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 59305 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48305 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 58905 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45805 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 58205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 47205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 57805 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46305 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 58705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 47705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 58305 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 57605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 46605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 57205 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 2.7_sqlite_pysqlite_dbapiunicode_cextensions 39705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 45805 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 3.7_sqlite_pysqlite_dbapiunicode_cextensions 42205 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 48605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 2.7_sqlite_pysqlite_dbapiunicode_cextensions 38605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 44705 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 3.7_sqlite_pysqlite_dbapiunicode_cextensions 41105 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 47505 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46905 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 59305 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48305 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 58905 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45805 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 58205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 47205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 57805 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46305 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 58705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 47705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 58305 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45205 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 57605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 46605 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 57205 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 26705 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 30505 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28805 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 32705 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 25905 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 29705 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28105 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 32005 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 26105 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 29905 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28205 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 32105 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 25305 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 29105 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 27505 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 31405 # TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set @@ -253,38 +267,38 @@ test.aaa_profiling.test_orm.BranchedOptionTest.test_generate_path_cache_key_unbo # TEST: test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45 -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 45 -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 3.7_sqlite_pysqlite_dbapiunicode_cextensions 58 -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 58 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 46 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 3.7_sqlite_pysqlite_dbapiunicode_cextensions 59 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 59 # TEST: test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 2.7_sqlite_pysqlite_dbapiunicode_cextensions 388 -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 388 -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 3.7_sqlite_pysqlite_dbapiunicode_cextensions 394 -test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 394 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 2.7_sqlite_pysqlite_dbapiunicode_cextensions 389 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 389 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 3.7_sqlite_pysqlite_dbapiunicode_cextensions 395 +test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 395 # TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_cextensions 17142 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 38148 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_cextensions 17177 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 38186 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_cextensions 17117 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 38123 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_cextensions 17147 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 38156 # TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols -test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 23248 -test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 32254 -test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 3.7_sqlite_pysqlite_dbapiunicode_cextensions 23290 -test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 32299 +test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 23244 +test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 32250 +test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 3.7_sqlite_pysqlite_dbapiunicode_cextensions 23287 +test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 32296 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 2.7_sqlite_pysqlite_dbapiunicode_cextensions 9903 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 9903 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 3.7_sqlite_pysqlite_dbapiunicode_cextensions 10354 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 10354 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 2.7_sqlite_pysqlite_dbapiunicode_cextensions 9303 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 9303 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 3.7_sqlite_pysqlite_dbapiunicode_cextensions 9754 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 9754 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain @@ -295,31 +309,31 @@ test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain 3.7_sqlite_pysql # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 2.7_sqlite_pysqlite_dbapiunicode_cextensions 95538 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 95738 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 3.7_sqlite_pysqlite_dbapiunicode_cextensions 103474 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 103674 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 2.7_sqlite_pysqlite_dbapiunicode_cextensions 92688 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 92888 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 3.7_sqlite_pysqlite_dbapiunicode_cextensions 100789 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 100789 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 2.7_sqlite_pysqlite_dbapiunicode_cextensions 93138 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 93338 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 3.7_sqlite_pysqlite_dbapiunicode_cextensions 101339 -test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 101539 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 2.7_sqlite_pysqlite_dbapiunicode_cextensions 90738 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 90938 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 3.7_sqlite_pysqlite_dbapiunicode_cextensions 99139 +test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 99139 # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_cextensions 457606 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 457611 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_cextensions 488272 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 488272 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_cextensions 443111 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 443111 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_cextensions 473672 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 473672 # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 429097 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 459697 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 434107 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 465007 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 446748 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 475548 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 452057 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 482357 # TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity @@ -330,24 +344,24 @@ test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_ # TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_cextensions 89508 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 93210 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_cextensions 91785 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 95789 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_cextensions 90536 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 94288 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_cextensions 93114 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 97118 # TEST: test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_cextensions 18394 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 18860 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_cextensions 19072 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 19626 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_cextensions 18487 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 18959 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_cextensions 19168 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 19720 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load -test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1014 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1048 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1054 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1092 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1007 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1041 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1047 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1085 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load @@ -358,24 +372,24 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_no_load 3.7_sqlite_pysqlite_dba # TEST: test.aaa_profiling.test_orm.QueryTest.test_query_cols -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 5694 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6974 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_cextensions 5922 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 7212 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 5584 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6864 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_cextensions 5792 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 7082 # TEST: test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 172195 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 193499 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 177018 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 196826 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 172456 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 194360 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 177281 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 197689 # TEST: test.aaa_profiling.test_orm.SessionTest.test_expire_lots -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1162 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1161 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1261 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1273 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1123 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1151 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1257 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1269 # TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect @@ -474,122 +488,122 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.7 # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mssql_pyodbc_dbapiunicode_cextensions 275 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6277 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_mysqldb_dbapiunicode_cextensions 317 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6339 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122273 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 128275 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 384 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36426 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 288 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6310 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 256 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6278 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mssql_pyodbc_dbapiunicode_cextensions 260 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6264 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_mysqldb_dbapiunicode_cextensions 293 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6297 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_pymysql_dbapiunicode_cextensions 88048 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_pymysql_dbapiunicode_nocextensions 94052 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_oracle_cx_oracle_dbapiunicode_cextensions 349 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6353 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_postgresql_psycopg2_dbapiunicode_cextensions 284 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6288 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_sqlite_pysqlite_dbapiunicode_cextensions 250 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6254 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mssql_pyodbc_dbapiunicode_cextensions 274 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6276 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_mysqldb_dbapiunicode_cextensions 316 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6338 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122272 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 128274 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 383 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36425 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 287 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6309 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 255 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6277 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mssql_pyodbc_dbapiunicode_cextensions 259 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6263 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_mysqldb_dbapiunicode_cextensions 292 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6296 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_pymysql_dbapiunicode_cextensions 88047 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_mysql_pymysql_dbapiunicode_nocextensions 94051 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_oracle_cx_oracle_dbapiunicode_cextensions 348 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6352 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_postgresql_psycopg2_dbapiunicode_cextensions 283 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6287 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_sqlite_pysqlite_dbapiunicode_cextensions 249 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6253 # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mssql_pyodbc_dbapiunicode_cextensions 275 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6277 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_mysqldb_dbapiunicode_cextensions 317 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6339 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122273 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 128275 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 384 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36426 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 288 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6310 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 256 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6278 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mssql_pyodbc_dbapiunicode_cextensions 260 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6264 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_mysqldb_dbapiunicode_cextensions 293 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6297 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_pymysql_dbapiunicode_cextensions 88048 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_pymysql_dbapiunicode_nocextensions 94052 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_oracle_cx_oracle_dbapiunicode_cextensions 349 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6353 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_postgresql_psycopg2_dbapiunicode_cextensions 284 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6288 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_sqlite_pysqlite_dbapiunicode_cextensions 250 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6254 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mssql_pyodbc_dbapiunicode_cextensions 274 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6276 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_mysqldb_dbapiunicode_cextensions 316 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6338 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122272 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 128274 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 383 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36425 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 287 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6309 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 255 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6277 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mssql_pyodbc_dbapiunicode_cextensions 259 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6263 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_mysqldb_dbapiunicode_cextensions 292 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6296 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_pymysql_dbapiunicode_cextensions 88047 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_mysql_pymysql_dbapiunicode_nocextensions 94051 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_oracle_cx_oracle_dbapiunicode_cextensions 348 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6352 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_postgresql_psycopg2_dbapiunicode_cextensions 283 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6287 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_sqlite_pysqlite_dbapiunicode_cextensions 249 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6253 # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_string -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mssql_pyodbc_dbapiunicode_cextensions 517 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6519 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_dbapiunicode_cextensions 522 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6524 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122488 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 128490 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 548 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36570 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 492 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6494 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 446 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6448 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mssql_pyodbc_dbapiunicode_cextensions 518 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6522 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_cextensions 523 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6527 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_pymysql_dbapiunicode_cextensions 88278 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_pymysql_dbapiunicode_nocextensions 94282 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_oracle_cx_oracle_dbapiunicode_cextensions 548 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6552 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_cextensions 513 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6517 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_cextensions 465 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6469 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mssql_pyodbc_dbapiunicode_cextensions 524 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6526 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_dbapiunicode_cextensions 529 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6531 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122495 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 128497 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 555 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36577 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 499 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6501 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 453 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6455 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mssql_pyodbc_dbapiunicode_cextensions 528 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6532 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_cextensions 533 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6537 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_pymysql_dbapiunicode_cextensions 88288 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_pymysql_dbapiunicode_nocextensions 94292 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_oracle_cx_oracle_dbapiunicode_cextensions 558 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6562 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_cextensions 523 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6527 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_cextensions 475 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6479 # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_unicode -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mssql_pyodbc_dbapiunicode_cextensions 517 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6519 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_dbapiunicode_cextensions 522 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6524 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122488 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 128490 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 548 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36570 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 492 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6494 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 446 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6448 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mssql_pyodbc_dbapiunicode_cextensions 518 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6522 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_cextensions 523 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6527 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_pymysql_dbapiunicode_cextensions 88278 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_pymysql_dbapiunicode_nocextensions 94282 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_oracle_cx_oracle_dbapiunicode_cextensions 548 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6552 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_cextensions 513 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6517 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_cextensions 465 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6469 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mssql_pyodbc_dbapiunicode_cextensions 524 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6526 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_dbapiunicode_cextensions 529 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6531 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122495 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 128497 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 555 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 36577 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 499 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6501 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 453 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6455 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mssql_pyodbc_dbapiunicode_cextensions 528 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mssql_pyodbc_dbapiunicode_nocextensions 6532 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_cextensions 533 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_nocextensions 6537 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_pymysql_dbapiunicode_cextensions 88288 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_pymysql_dbapiunicode_nocextensions 94292 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_oracle_cx_oracle_dbapiunicode_cextensions 558 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 6562 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_cextensions 523 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6527 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_cextensions 475 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6479 # TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6462,328,4212,12379,1308,2185,2749 -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6500,328,4276,12943,1430,2201,2937 -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 6307,311,4188,12346,1299,2142,2798 -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6384,311,4268,12954,1430,2164,2992 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6454,327,4284,12623,1310,2206,2716 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6509,327,4348,13185,1433,2222,2900 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 6244,310,4276,12644,1310,2163,2774 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6321,310,4356,13252,1441,2185,2968 # TEST: test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 7085,440,6993,18134,1321,2795 -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 7262,450,7225,20437,1433,2853 -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 7124,432,7213,18746,1313,2876 -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 7272,440,7469,21112,1434,2944 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 7054,442,6906,17933,1323,2823 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 7230,452,7138,20236,1436,2882 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 7093,434,7126,18551,1324,2910 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 7241,442,7382,20917,1445,2978 diff --git a/test/sql/test_compare.py b/test/sql/test_compare.py index ab612053eb..2800f8248c 100644 --- a/test/sql/test_compare.py +++ b/test/sql/test_compare.py @@ -61,6 +61,7 @@ from sqlalchemy.sql.visitors import InternalTraversal from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_false +from sqlalchemy.testing import is_not_ from sqlalchemy.testing import is_true from sqlalchemy.testing import ne_ from sqlalchemy.testing.util import random_choices @@ -174,6 +175,14 @@ class CoreFixtures(object): table_a.c.a._annotate( {"orm": True, "parententity": MyEntity("b", select([table_a]))} ), + table_a.c.a._annotate( + { + "orm": True, + "parententity": MyEntity( + "b", select([table_a]).where(table_a.c.a == 5) + ), + } + ), ), lambda: ( table_a, @@ -759,6 +768,43 @@ class CacheKeyTest(CacheKeyFixture, CoreFixtures, fixtures.TestBase): f1._copy_internals() f2._copy_internals() + def test_generative_cache_key_regen(self): + t1 = table("t1", column("a"), column("b")) + + s1 = select([t1]) + + ck1 = s1._generate_cache_key() + + s2 = s1.where(t1.c.a == 5) + + ck2 = s2._generate_cache_key() + + ne_(ck1, ck2) + is_not_(ck1, None) + is_not_(ck2, None) + + def test_generative_cache_key_regen_w_del(self): + t1 = table("t1", column("a"), column("b")) + + s1 = select([t1]) + + ck1 = s1._generate_cache_key() + + s2 = s1.where(t1.c.a == 5) + + del s1 + + # there is now a good chance that id(s3) == id(s1), make sure + # cache key is regenerated + + s3 = s2.order_by(t1.c.b) + + ck3 = s3._generate_cache_key() + + ne_(ck1, ck3) + is_not_(ck1, None) + is_not_(ck3, None) + class CompareAndCopyTest(CoreFixtures, fixtures.TestBase): @classmethod diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index 151ecb1d25..e44deed90d 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -3344,6 +3344,116 @@ class BindParameterTest(AssertsCompiledSQL, fixtures.TestBase): _group_number=2, ) + @testing.combinations( + ( + select([table1]).where(table1.c.myid == 5), + select([table1]).where(table1.c.myid == 10), + {"myid_1": 5}, + {"myid_1": 10}, + None, + None, + ), + ( + select([table1]).where( + table1.c.myid + == bindparam(None, unique=True, callable_=lambda: 5) + ), + select([table1]).where( + table1.c.myid + == bindparam(None, unique=True, callable_=lambda: 10) + ), + {"param_1": 5}, + {"param_1": 10}, + None, + None, + ), + ( + table1.update() + .where(table1.c.myid == 5) + .values(name="n1", description="d1"), + table1.update() + .where(table1.c.myid == 10) + .values(name="n2", description="d2"), + {"description": "d1", "myid_1": 5, "name": "n1"}, + {"description": "d2", "myid_1": 10, "name": "n2"}, + None, + None, + ), + ( + table1.update().where(table1.c.myid == 5), + table1.update().where(table1.c.myid == 10), + {"description": "d1", "myid_1": 5, "name": "n1"}, + {"description": "d2", "myid_1": 10, "name": "n2"}, + {"description": "d1", "name": "n1"}, + {"description": "d2", "name": "n2"}, + ), + ( + table1.update().where( + table1.c.myid + == bindparam(None, unique=True, callable_=lambda: 5) + ), + table1.update().where( + table1.c.myid + == bindparam(None, unique=True, callable_=lambda: 10) + ), + {"description": "d1", "param_1": 5, "name": "n1"}, + {"description": "d2", "param_1": 10, "name": "n2"}, + {"description": "d1", "name": "n1"}, + {"description": "d2", "name": "n2"}, + ), + ( + union( + select([table1]).where(table1.c.myid == 5), + select([table1]).where(table1.c.myid == 12), + ), + union( + select([table1]).where(table1.c.myid == 5), + select([table1]).where(table1.c.myid == 15), + ), + {"myid_1": 5, "myid_2": 12}, + {"myid_1": 5, "myid_2": 15}, + None, + None, + ), + ) + def test_construct_params_combine_extracted( + self, stmt1, stmt2, param1, param2, extparam1, extparam2 + ): + + if extparam1: + keys = list(extparam1) + else: + keys = [] + + s1_cache_key = stmt1._generate_cache_key() + s1_compiled = stmt1.compile(cache_key=s1_cache_key, column_keys=keys) + + s2_cache_key = stmt2._generate_cache_key() + + eq_(s1_compiled.construct_params(params=extparam1), param1) + eq_( + s1_compiled.construct_params( + params=extparam1, extracted_parameters=s1_cache_key[1] + ), + param1, + ) + + eq_( + s1_compiled.construct_params( + params=extparam2, extracted_parameters=s2_cache_key[1] + ), + param2, + ) + + s1_compiled_no_cache_key = stmt1.compile() + assert_raises_message( + exc.CompileError, + "This compiled object has no original cache key; can't pass " + "extracted_parameters to construct_params", + s1_compiled_no_cache_key.construct_params, + extracted_parameters=s1_cache_key[1], + ) + def test_tuple_expanding_in_no_values(self): expr = tuple_(table1.c.myid, table1.c.name).in_( [(1, "foo"), (5, "bar")] @@ -5021,7 +5131,7 @@ class ResultMapTest(fixtures.TestBase): stmt = select([t.c.x, t.c.y, l1, t.c.y, l2, t.c.x, l3]) # so the statement has 7 inner columns... - eq_(len(list(stmt.inner_columns)), 7) + eq_(len(list(stmt.selected_columns)), 7) # 7 are exposed as of 1.4, no more deduping eq_(len(stmt.subquery().c), 7) diff --git a/test/sql/test_external_traversal.py b/test/sql/test_external_traversal.py index ac423931fd..37fb752fe1 100644 --- a/test/sql/test_external_traversal.py +++ b/test/sql/test_external_traversal.py @@ -172,7 +172,7 @@ class TraversalTest(fixtures.TestBase, AssertsExecutionResults): vis = Vis() s2 = vis.traverse(s1) - eq_(list(s2.inner_columns)[0].anon_label, c1.anon_label) + eq_(list(s2.selected_columns)[0].anon_label, c1.anon_label) def test_change_in_place(self): struct = B( diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py index fd3f557803..5a6e6252b4 100644 --- a/test/sql/test_functions.py +++ b/test/sql/test_functions.py @@ -468,9 +468,12 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): "my_func(:my_func_1, :my_func_2, NULL, :my_func_3)", ) + f1 = func.my_func(1, 2, None, 3) + f1._generate_cache_key() + # test pickling self.assert_compile( - util.pickle.loads(util.pickle.dumps(func.my_func(1, 2, None, 3))), + util.pickle.loads(util.pickle.dumps(f1)), "my_func(:my_func_1, :my_func_2, NULL, :my_func_3)", ) diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py index f08248440b..253ad7b38e 100644 --- a/test/sql/test_resultset.py +++ b/test/sql/test_resultset.py @@ -29,9 +29,11 @@ from sqlalchemy.engine import default from sqlalchemy.engine import result as _result from sqlalchemy.engine import Row from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql import ColumnElement from sqlalchemy.sql import expression from sqlalchemy.sql.selectable import TextualSelect from sqlalchemy.sql.sqltypes import NULLTYPE +from sqlalchemy.sql.util import ClauseAdapter from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import assertions @@ -1391,16 +1393,20 @@ class KeyTargetingTest(fixtures.TablesTest): @classmethod def insert_data(cls): - cls.tables.keyed1.insert().execute(dict(b="a1", q="c1")) - cls.tables.keyed2.insert().execute(dict(a="a2", b="b2")) - cls.tables.keyed3.insert().execute(dict(a="a3", d="d3")) - cls.tables.keyed4.insert().execute(dict(b="b4", q="q4")) - cls.tables.content.insert().execute(type="t1") - - if testing.requires.schemas.enabled: - cls.tables[ - "%s.wschema" % testing.config.test_schema - ].insert().execute(dict(b="a1", q="c1")) + with testing.db.begin() as conn: + conn.execute(cls.tables.keyed1.insert(), dict(b="a1", q="c1")) + conn.execute(cls.tables.keyed2.insert(), dict(a="a2", b="b2")) + conn.execute(cls.tables.keyed3.insert(), dict(a="a3", d="d3")) + conn.execute(cls.tables.keyed4.insert(), dict(b="b4", q="q4")) + conn.execute(cls.tables.content.insert(), dict(type="t1")) + + if testing.requires.schemas.enabled: + conn.execute( + cls.tables[ + "%s.wschema" % testing.config.test_schema + ].insert(), + dict(b="a1", q="c1"), + ) @testing.requires.schemas def test_keyed_accessor_wschema(self): @@ -1712,6 +1718,87 @@ class KeyTargetingTest(fixtures.TablesTest): in_(stmt.selected_columns.keyed2_a, row._mapping) in_(stmt.selected_columns.keyed2_b, row._mapping) + def _adapt_result_columns_fixture_one(self): + keyed1 = self.tables.keyed1 + stmt = ( + select([keyed1.c.b, keyed1.c.q.label("foo")]) + .apply_labels() + .subquery() + ) + + return select([stmt.c.keyed1_b, stmt.c.foo]) + + def _adapt_result_columns_fixture_two(self): + return text("select a AS keyed2_a, b AS keyed2_b from keyed2").columns( + keyed2_a=CHAR, keyed2_b=CHAR + ) + + def _adapt_result_columns_fixture_three(self): + keyed1 = self.tables.keyed1 + stmt = select([keyed1.c.b, keyed1.c.q.label("foo")]).subquery() + + return select([stmt.c.b, stmt.c.foo]) + + def _adapt_result_columns_fixture_four(self): + keyed1 = self.tables.keyed1 + + stmt1 = select([keyed1]).apply_labels() + + a1 = keyed1.alias() + stmt2 = ClauseAdapter(a1).traverse(stmt1) + + return stmt2 + + @testing.combinations( + _adapt_result_columns_fixture_one, + _adapt_result_columns_fixture_two, + _adapt_result_columns_fixture_three, + _adapt_result_columns_fixture_four, + argnames="stmt_fn", + ) + def test_adapt_result_columns(self, connection, stmt_fn): + """test adaptation of a CursorResultMetadata to another one. + + + This copies the _keymap from one to the other in terms of the + selected columns of a target selectable. + + This is used by the statement caching process to re-use the + CursorResultMetadata from the cached statement against the same + statement sent separately. + + """ + + stmt1 = stmt_fn(self) + stmt2 = stmt_fn(self) + + eq_(stmt1._generate_cache_key(), stmt2._generate_cache_key()) + + column_linkage = dict( + zip(stmt1.selected_columns, stmt2.selected_columns) + ) + + result = connection.execute(stmt1) + + mock_context = Mock( + compiled=result.context.compiled, invoked_statement=stmt2 + ) + existing_metadata = result._metadata + adapted_metadata = existing_metadata._adapt_to_context(mock_context) + + eq_(existing_metadata.keys, adapted_metadata.keys) + + for k in existing_metadata._keymap: + if isinstance(k, ColumnElement) and k in column_linkage: + other_k = column_linkage[k] + else: + other_k = k + + is_( + existing_metadata._keymap[k], adapted_metadata._keymap[other_k] + ) + return stmt1, existing_metadata, stmt2, adapted_metadata + class PositionalTextTest(fixtures.TablesTest): run_inserts = "once" diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index 58e7ee6a17..8fb1f29510 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -1973,10 +1973,10 @@ class ReduceTest(fixtures.TestBase, AssertsExecutionResults): ) s1 = select([t1, t2]) s2 = s1.reduce_columns(only_synonyms=False) - eq_(set(s2.inner_columns), set([t1.c.x, t1.c.y, t2.c.q])) + eq_(set(s2.selected_columns), set([t1.c.x, t1.c.y, t2.c.q])) s2 = s1.reduce_columns() - eq_(set(s2.inner_columns), set([t1.c.x, t1.c.y, t2.c.z, t2.c.q])) + eq_(set(s2.selected_columns), set([t1.c.x, t1.c.y, t2.c.z, t2.c.q])) def test_reduce_only_synonym_fk(self): m = MetaData() @@ -2019,7 +2019,7 @@ class ReduceTest(fixtures.TestBase, AssertsExecutionResults): s1 = select([t1]).subquery() s2 = select([t1, s1]).where(t1.c.x == s1.c.x).where(s1.c.y == t1.c.z) eq_( - set(s2.reduce_columns().inner_columns), + set(s2.reduce_columns().selected_columns), set([t1.c.x, t1.c.y, t1.c.z, s1.c.y, s1.c.z]), ) @@ -2027,7 +2027,7 @@ class ReduceTest(fixtures.TestBase, AssertsExecutionResults): s1 = select([t1]).subquery() s2 = select([s1, t1]).where(t1.c.x == s1.c.x).where(s1.c.y == t1.c.z) eq_( - set(s2.reduce_columns().inner_columns), + set(s2.reduce_columns().selected_columns), set([s1.c.x, t1.c.y, t1.c.z, s1.c.y, s1.c.z]), ) -- 2.47.3