diff options
-rw-r--r-- | doc/build/changelog/migration_14.rst | 80 | ||||
-rw-r--r-- | doc/build/changelog/unreleased_14/4753.rst | 21 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/oracle/base.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 9 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/query.py | 21 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/base.py | 447 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 44 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/dml.py | 5 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 28 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/functions.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/schema.py | 44 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/selectable.py | 64 | ||||
-rw-r--r-- | test/base/test_utils.py | 559 | ||||
-rw-r--r-- | test/engine/test_reflection.py | 16 | ||||
-rw-r--r-- | test/profiles.txt | 432 | ||||
-rw-r--r-- | test/sql/test_compiler.py | 51 | ||||
-rw-r--r-- | test/sql/test_cte.py | 6 | ||||
-rw-r--r-- | test/sql/test_join_rewriting.py | 156 | ||||
-rw-r--r-- | test/sql/test_metadata.py | 3 | ||||
-rw-r--r-- | test/sql/test_selectable.py | 85 |
20 files changed, 1431 insertions, 646 deletions
diff --git a/doc/build/changelog/migration_14.rst b/doc/build/changelog/migration_14.rst index f0e99e7ea..1fa89c2ae 100644 --- a/doc/build/changelog/migration_14.rst +++ b/doc/build/changelog/migration_14.rst @@ -394,6 +394,86 @@ configured to raise an exception using the Python warnings filter. Behavior Changes - Core ======================== +.. _change_4753: + +SELECT objects and derived FROM clauses allow for duplicate columns and column labels +------------------------------------------------------------------------------------- + +This change allows that the :func:`.select` construct now allows for duplicate +column labels as well as duplicate column objects themselves, so that result +tuples are organized and ordered in the identical way in that the columns were +selected. The ORM :class:`.Query` already works this way, so this change +allows for greater cross-compatibility between the two, which is a key goal of +the 2.0 transition:: + + >>> from sqlalchemy import column, select + >>> c1, c2, c3, c4 = column('c1'), column('c2'), column('c3'), column('c4') + >>> stmt = select([c1, c2, c3.label('c2'), c2, c4]) + >>> print(stmt) + SELECT c1, c2, c3 AS c2, c2, c4 + +To support this change, the :class:`.ColumnCollection` used by +:class:`.SelectBase` as well as for derived FROM clauses such as subqueries +also support duplicate columns; this includes the new +:attr:`.SelectBase.selected_columns` attribute, the deprecated ``SelectBase.c`` +attribute, as well as the :attr:`.FromClause.c` attribute seen on constructs +such as :class:`.Subquery` and :class:`.Alias`:: + + >>> list(stmt.selected_columns) + [ + <sqlalchemy.sql.elements.ColumnClause at 0x7fa540bcca20; c1>, + <sqlalchemy.sql.elements.ColumnClause at 0x7fa540bcc9e8; c2>, + <sqlalchemy.sql.elements.Label object at 0x7fa540b3e2e8>, + <sqlalchemy.sql.elements.ColumnClause at 0x7fa540bcc9e8; c2>, + <sqlalchemy.sql.elements.ColumnClause at 0x7fa540897048; c4> + ] + + >>> print(stmt.subquery().select()) + SELECT anon_1.c1, anon_1.c2, anon_1.c2, anon_1.c2, anon_1.c4 + FROM (SELECT c1, c2, c3 AS c2, c2, c4) AS anon_1 + +:class:`.ColumnCollection` also allows access by integer index to support +when the string "key" is ambiguous:: + + >>> stmt.selected_columns[2] + <sqlalchemy.sql.elements.Label object at 0x7fa540b3e2e8> + +To suit the use of :class:`.ColumnCollection` in objects such as +:class:`.Table` and :class:`.PrimaryKeyConstraint`, the old "deduplicating" +behavior which is more critical for these objects is preserved in a new class +:class:`.DedupeColumnCollection`. + +The change includes that the familiar warning ``"Column %r on table %r being +replaced by %r, which has the same key. Consider use_labels for select() +statements."`` is **removed**; the :meth:`.Select.apply_labels` is still +available and is still used by the ORM for all SELECT operations, however it +does not imply deduplication of column objects, although it does imply +deduplication of implicitly generated labels:: + + >>> from sqlalchemy import table + >>> user = table('user', column('id'), column('name')) + >>> stmt = select([user.c.id, user.c.name, user.c.id]).apply_labels() + >>> print(stmt) + SELECT "user".id AS user_id, "user".name AS user_name, "user".id AS id_1 + FROM "user" + +Finally, the change makes it easier to create UNION and other +:class:`.CompoundSelect` objects, by ensuring that the number and position +of columns in a SELECT statement mirrors what was given, in a use case such +as:: + + >>> s1 = select([user, user.c.id]) + >>> s2 = select([c1, c2, c3]) + >>> from sqlalchemy import union + >>> u = union(s1, s2) + >>> print(u) + SELECT "user".id, "user".name, "user".id + FROM "user" UNION SELECT c1, c2, c3 + + + +:ticket:`4753` + .. _change_4712: Connection-level transactions can now be inactive based on subtransaction diff --git a/doc/build/changelog/unreleased_14/4753.rst b/doc/build/changelog/unreleased_14/4753.rst new file mode 100644 index 000000000..50617feec --- /dev/null +++ b/doc/build/changelog/unreleased_14/4753.rst @@ -0,0 +1,21 @@ +.. change:: + :tags: change,engine + :tickets: 4753 + + The :func:`.select` construct and related constructs now allow for + duplication of column labels and columns themselves in the columns clause, + mirroring exactly how column expressions were passed in. This allows + the tuples returned by an executed result to match what was SELECTed + for in the first place, which is how the ORM :class:`.Query` works, so + this establishes better cross-compatibility between the two constructs. + Additionally, it allows column-positioning-sensitive structures such as + UNIONs (i.e. :class:`.CompoundSelect`) to be more intuitively constructed + in those cases where a particular column might appear in more than one + place. To support this change, the :class:`.ColumnCollection` has been + revised to support duplicate columns as well as to allow integer index + access. + + .. seealso:: + + :ref:`change_4753` + diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 842730c5b..868c64ed3 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -878,7 +878,8 @@ class OracleCompiler(compiler.SQLCompiler): for_update._copy_internals() for elem in for_update.of: - select = select.column(elem) + if not select.selected_columns.contains_column(elem): + select = select.column(elem) # Wrap the middle select and add the hint inner_subquery = select.alias() diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 33a474576..5e8d25647 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -45,6 +45,7 @@ from .. import log from .. import schema from .. import sql from .. import util +from ..sql import base as sql_base from ..sql import coercions from ..sql import expression from ..sql import operators @@ -1455,7 +1456,11 @@ class Mapper(InspectionAttr): def _configure_properties(self): # Column and other ClauseElement objects which are mapped - self.columns = self.c = util.OrderedProperties() + + # TODO: technically this should be a DedupeColumnCollection + # however DCC needs changes and more tests to fully cover + # storing columns under a separate key name + self.columns = self.c = sql_base.ColumnCollection() # object attribute names mapped to MapperProperty objects self._props = util.OrderedDict() @@ -1781,7 +1786,7 @@ class Mapper(InspectionAttr): or prop.columns[0] is self.polymorphic_on ) - self.columns[key] = col + self.columns.add(col, key) for col in prop.columns + prop._orig_columns: for col in col.proxy_set: self._columntoproperty[col] = prop diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 13402e7f4..b5c49ee05 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -528,7 +528,7 @@ class Query(object): """ - stmt = self._compile_context(labels=self._with_labels).statement + stmt = self._compile_context(for_statement=True).statement if self._params: stmt = stmt.params(self._params) @@ -3843,7 +3843,7 @@ class Query(object): update_op.exec_() return update_op.rowcount - def _compile_context(self, labels=True): + def _compile_context(self, for_statement=False): if self.dispatch.before_compile: for fn in self.dispatch.before_compile: new_query = fn(self) @@ -3855,7 +3855,8 @@ class Query(object): if context.statement is not None: return context - context.labels = labels + context.labels = not for_statement or self._with_labels + context.dedupe_cols = True context._for_update_arg = self._for_update_arg @@ -3909,7 +3910,9 @@ class Query(object): order_by_col_expr = [] inner = sql.select( - context.primary_columns + order_by_col_expr, + util.unique_list(context.primary_columns + order_by_col_expr) + if context.dedupe_cols + else (context.primary_columns + order_by_col_expr), context.whereclause, from_obj=context.froms, use_labels=context.labels, @@ -3979,7 +3982,11 @@ class Query(object): context.froms += tuple(context.eager_joins.values()) statement = sql.select( - context.primary_columns + context.secondary_columns, + util.unique_list( + context.primary_columns + context.secondary_columns + ) + if context.dedupe_cols + else (context.primary_columns + context.secondary_columns), context.whereclause, from_obj=context.froms, use_labels=context.labels, @@ -4290,8 +4297,7 @@ class Bundle(InspectionAttr): """ self.name = self._label = name self.exprs = exprs - self.c = self.columns = ColumnCollection() - self.columns.update( + self.c = self.columns = ColumnCollection( (getattr(col, "key", col._label), col) for col in exprs ) self.single_entity = kw.pop("single_entity", self.single_entity) @@ -4658,6 +4664,7 @@ class QueryContext(object): "whereclause", "order_by", "labels", + "dedupe_cols", "_for_update_arg", "runid", "partials", diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py index a84843c4b..da384bdab 100644 --- a/lib/sqlalchemy/sql/base.py +++ b/lib/sqlalchemy/sql/base.py @@ -499,26 +499,209 @@ class SchemaVisitor(ClauseVisitor): __traverse_options__ = {"schema_visitor": True} -class ColumnCollection(util.OrderedProperties): - """An ordered dictionary that stores a list of ColumnElement - instances. +class ColumnCollection(object): + """Collection of :class:`.ColumnElement` instances, typically for + selectables. + + The :class:`.ColumnCollection` has both mapping- and sequence- like + behaviors. A :class:`.ColumnCollection` usually stores :class:`.Column` + objects, which are then accessible both via mapping style access as well + as attribute access style. The name for which a :class:`.Column` would + be present is normally that of the :paramref:`.Column.key` parameter, + however depending on the context, it may be stored under a special label + name:: + + >>> from sqlalchemy import Column, Integer + >>> from sqlalchemy.sql import ColumnCollection + >>> x, y = Column('x', Integer), Column('y', Integer) + >>> cc = ColumnCollection(columns=[x, y]) + >>> cc.x + Column('x', Integer(), table=None) + >>> cc.y + Column('y', Integer(), table=None) + >>> cc['x'] + Column('x', Integer(), table=None) + >>> cc['y'] + + :class`.ColumnCollection` also indexes the columns in order and allows + them to be accessible by their integer position:: + + >>> cc[0] + Column('x', Integer(), table=None) + >>> cc[1] + Column('y', Integer(), table=None) + + .. versionadded:: 1.4 :class:`.ColumnCollection` allows integer-based + index access to the collection. + + Iterating the collection yields the column expressions in order:: + + >>> list(cc) + [Column('x', Integer(), table=None), + Column('y', Integer(), table=None)] + + The base :class:`.ColumnCollection` object can store duplicates, which can + mean either two columns with the same key, in which case the column + returned by key access is **arbitrary**:: + + >>> x1, x2 = Column('x', Integer), Column('x', Integer) + >>> cc = ColumnCollection(columns=[x1, x2]) + >>> list(cc) + [Column('x', Integer(), table=None), + Column('x', Integer(), table=None)] + >>> cc['x'] is x1 + False + >>> cc['x'] is x2 + True + + Or it can also mean the same column multiple times. These cases are + supported as :class:`.ColumnCollection` is used to represent the columns in + a SELECT statement which may include duplicates. + + A special subclass :class:`.DedupeColumnCollection` exists which instead + maintains SQLAlchemy's older behavior of not allowing duplicates; this + collection is used for schema level objects like :class:`.Table` and + :class:`.PrimaryKeyConstraint` where this deduping is helpful. The + :class:`.DedupeColumnCollection` class also has additional mutation methods + as the schema constructs have more use cases that require removal and + replacement of columns. + + .. versionchanged:: 1.4 :class:`.ColumnCollection` now stores duplicate + column keys as well as the same column in multiple positions. The + :class:`.DedupeColumnCollection` class is added to maintain the + former behavior in those cases where deduplication as well as + additional replace/remove operations are needed. - Overrides the ``__eq__()`` method to produce SQL clauses between - sets of correlated columns. """ - __slots__ = "_all_columns" + __slots__ = "_collection", "_index", "_colset" - def __init__(self, *columns): - super(ColumnCollection, self).__init__() - object.__setattr__(self, "_all_columns", []) - for c in columns: - self.add(c) + def __init__(self, columns=None): + object.__setattr__(self, "_colset", set()) + object.__setattr__(self, "_index", {}) + object.__setattr__(self, "_collection", []) + if columns: + self._initial_populate(columns) + + def _initial_populate(self, iter_): + self._populate_separate_keys(iter_) + + @property + def _all_columns(self): + return [col for (k, col) in self._collection] + + def keys(self): + return [k for (k, col) in self._collection] + + def __len__(self): + return len(self._collection) + + def __iter__(self): + # turn to a list first to maintain over a course of changes + return iter([col for k, col in self._collection]) + + def __getitem__(self, key): + try: + return self._index[key] + except KeyError: + if isinstance(key, util.int_types): + raise IndexError(key) + else: + raise + + def __getattr__(self, key): + try: + return self._index[key] + except KeyError: + raise AttributeError(key) + + def __contains__(self, key): + if key not in self._index: + if not isinstance(key, util.string_types): + raise exc.ArgumentError( + "__contains__ requires a string argument" + ) + return False + else: + return True + + def compare(self, other): + for l, r in util.zip_longest(self, other): + if l is not r: + return False + else: + return True + + def __eq__(self, other): + return self.compare(other) + + def get(self, key, default=None): + if key in self._index: + return self._index[key] + else: + return default def __str__(self): return repr([str(c) for c in self]) + def __setitem__(self, key, value): + raise NotImplementedError() + + def __delitem__(self, key): + raise NotImplementedError() + + def __setattr__(self, key, obj): + raise NotImplementedError() + + def clear(self): + raise NotImplementedError() + + def remove(self, column): + raise NotImplementedError() + + def update(self, iter_): + raise NotImplementedError() + + __hash__ = None + + def _populate_separate_keys(self, iter_): + """populate from an iterator of (key, column)""" + cols = list(iter_) + self._collection[:] = cols + self._colset.update(c for k, c in self._collection) + self._index.update( + (idx, c) for idx, (k, c) in enumerate(self._collection) + ) + self._index.update({k: col for k, col in reversed(self._collection)}) + + def add(self, column, key=None): + if key is None: + key = column.key + + l = len(self._collection) + self._collection.append((key, column)) + self._colset.add(column) + self._index[l] = column + if key not in self._index: + self._index[key] = column + + def __getstate__(self): + return {"_collection": self._collection, "_index": self._index} + + def __setstate__(self, state): + object.__setattr__(self, "_index", state["_index"]) + object.__setattr__(self, "_collection", state["_collection"]) + object.__setattr__( + self, "_colset", {col for k, col in self._collection} + ) + + def contains_column(self, col): + return col in self._colset + + def as_immutable(self): + return ImmutableColumnCollection(self) + def corresponding_column(self, column, require_embedded=False): """Given a :class:`.ColumnElement`, return the exported :class:`.ColumnElement` object from this :class:`.ColumnCollection` @@ -554,11 +737,11 @@ class ColumnCollection(util.OrderedProperties): return True # don't dig around if the column is locally present - if self.contains_column(column): + if column in self._colset: return column col, intersect = None, None target_set = column.proxy_set - cols = self._all_columns + cols = [c for (k, c) in self._collection] for c in cols: expanded_proxy_set = set(_expand_cloned(c.proxy_set)) i = target_set.intersection(expanded_proxy_set) @@ -610,165 +793,167 @@ class ColumnCollection(util.OrderedProperties): col, intersect = c, i return col - def replace(self, column): - """add the given column to this collection, removing unaliased - versions of this column as well as existing columns with the - same key. - e.g.:: +class DedupeColumnCollection(ColumnCollection): + """A :class:`.ColumnCollection that maintains deduplicating behavior. - t = Table('sometable', metadata, Column('col1', Integer)) - t.columns.replace(Column('col1', Integer, key='columnone')) + This is useful by schema level objects such as :class:`.Table` and + :class:`.PrimaryKeyConstraint`. The collection includes more + sophisticated mutator methods as well to suit schema objects which + require mutable column collections. - will remove the original 'col1' from the collection, and add - the new column under the name 'columnname'. - - Used by schema.Column to override columns during table reflection. - - """ - remove_col = None - if column.name in self and column.key != column.name: - other = self[column.name] - if other.name == other.key: - remove_col = other - del self._data[other.key] - - if column.key in self._data: - remove_col = self._data[column.key] - - self._data[column.key] = column - if remove_col is not None: - self._all_columns[:] = [ - column if c is remove_col else c for c in self._all_columns - ] - else: - self._all_columns.append(column) + .. versionadded: 1.4 - def add(self, column): - """Add a column to this collection. + """ - The key attribute of the column will be used as the hash key - for this dictionary. + def add(self, column, key=None): + if key is not None and column.key != key: + raise exc.ArgumentError( + "DedupeColumnCollection requires columns be under " + "the same key as their .key" + ) + key = column.key - """ - if not column.key: + if key is None: raise exc.ArgumentError( "Can't add unnamed column to column collection" ) - self[column.key] = column - - def __delitem__(self, key): - raise NotImplementedError() - - def __setattr__(self, key, obj): - raise NotImplementedError() - def __setitem__(self, key, value): - if key in self: + if key in self._index: - # this warning is primarily to catch select() statements - # which have conflicting column names in their exported - # columns collection + existing = self._index[key] - existing = self[key] - - if existing is value: + if existing is column: return - if not existing.shares_lineage(value): - util.warn( - "Column %r on table %r being replaced by " - "%r, which has the same key. Consider " - "use_labels for select() statements." - % (key, getattr(existing, "table", None), value) - ) + self.replace(column) # pop out memoized proxy_set as this # operation may very well be occurring # in a _make_proxy operation - util.memoized_property.reset(value, "proxy_set") + util.memoized_property.reset(column, "proxy_set") + else: + l = len(self._collection) + self._collection.append((key, column)) + self._colset.add(column) + self._index[l] = column + self._index[key] = column + + def _populate_separate_keys(self, iter_): + """populate from an iterator of (key, column)""" + cols = list(iter_) - self._all_columns.append(value) - self._data[key] = value + replace_col = [] + for k, col in cols: + if col.key != k: + raise exc.ArgumentError( + "DedupeColumnCollection requires columns be under " + "the same key as their .key" + ) + if col.name in self._index and col.key != col.name: + replace_col.append(col) + elif col.key in self._index: + replace_col.append(col) + else: + self._index[k] = col + self._collection.append((k, col)) + self._colset.update(c for (k, c) in self._collection) + self._index.update( + (idx, c) for idx, (k, c) in enumerate(self._collection) + ) + for col in replace_col: + self.replace(col) - def clear(self): - raise NotImplementedError() + def extend(self, iter_): + self._populate_separate_keys((col.key, col) for col in iter_) def remove(self, column): - del self._data[column.key] - self._all_columns[:] = [ - c for c in self._all_columns if c is not column + if column not in self._colset: + raise ValueError( + "Can't remove column %r; column is not in this collection" + % column + ) + del self._index[column.key] + self._colset.remove(column) + self._collection[:] = [ + (k, c) for (k, c) in self._collection if c is not column ] - - def update(self, iter_): - cols = list(iter_) - all_col_set = set(self._all_columns) - self._all_columns.extend( - c for label, c in cols if c not in all_col_set + self._index.update( + {idx: col for idx, (k, col) in enumerate(self._collection)} ) - self._data.update((label, c) for label, c in cols) + # delete higher index + del self._index[len(self._collection)] - def extend(self, iter_): - cols = list(iter_) - all_col_set = set(self._all_columns) - self._all_columns.extend(c for c in cols if c not in all_col_set) - self._data.update((c.key, c) for c in cols) + def replace(self, column): + """add the given column to this collection, removing unaliased + versions of this column as well as existing columns with the + same key. - __hash__ = None + e.g.:: - def __eq__(self, other): - l = [] - for c in getattr(other, "_all_columns", other): - for local in self._all_columns: - if c.shares_lineage(local): - l.append(c == local) - return elements.and_(*l) + t = Table('sometable', metadata, Column('col1', Integer)) + t.columns.replace(Column('col1', Integer, key='columnone')) - def __contains__(self, other): - if not isinstance(other, util.string_types): - raise exc.ArgumentError("__contains__ requires a string argument") - return util.OrderedProperties.__contains__(self, other) + will remove the original 'col1' from the collection, and add + the new column under the name 'columnname'. - def __getstate__(self): - return {"_data": self._data, "_all_columns": self._all_columns} + Used by schema.Column to override columns during table reflection. - def __setstate__(self, state): - object.__setattr__(self, "_data", state["_data"]) - object.__setattr__(self, "_all_columns", state["_all_columns"]) + """ - def contains_column(self, col): - return col in set(self._all_columns) + remove_col = set() + # remove up to two columns based on matches of name as well as key + if column.name in self._index and column.key != column.name: + other = self._index[column.name] + if other.name == other.key: + remove_col.add(other) + + if column.key in self._index: + remove_col.add(self._index[column.key]) + + new_cols = [] + replaced = False + for k, col in self._collection: + if col in remove_col: + if not replaced: + replaced = True + new_cols.append((column.key, column)) + else: + new_cols.append((k, col)) - def as_immutable(self): - return ImmutableColumnCollection(self._data, self._all_columns) + if remove_col: + self._colset.difference_update(remove_col) + if not replaced: + new_cols.append((column.key, column)) -class SeparateKeyColumnCollection(ColumnCollection): - """Column collection that maintains a string name separate from the - column itself""" + self._colset.add(column) + self._collection[:] = new_cols - def __init__(self, cols_plus_names=None): - super(ColumnCollection, self).__init__() - object.__setattr__(self, "_all_columns", []) - if cols_plus_names: - self.update(cols_plus_names) + self._index.clear() + self._index.update( + {idx: col for idx, (k, col) in enumerate(self._collection)} + ) + self._index.update(self._collection) - def replace(self, column): - raise NotImplementedError() - def add(self, column): - raise NotImplementedError() +class ImmutableColumnCollection(util.ImmutableContainer, ColumnCollection): + __slots__ = ("_parent",) - def remove(self, column): - raise NotImplementedError() + def __init__(self, collection): + object.__setattr__(self, "_parent", collection) + object.__setattr__(self, "_colset", collection._colset) + object.__setattr__(self, "_index", collection._index) + object.__setattr__(self, "_collection", collection._collection) + def __getstate__(self): + return {"_parent": self._parent} -class ImmutableColumnCollection(util.ImmutableProperties, ColumnCollection): - def __init__(self, data, all_columns): - util.ImmutableProperties.__init__(self, data) - object.__setattr__(self, "_all_columns", all_columns) + def __setstate__(self, state): + parent = state["_parent"] + self.__init__(parent) - extend = remove = util.ImmutableProperties._immutable + add = extend = remove = util.ImmutableContainer._immutable class ColumnSet(util.ordered_column_set): diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 13219ee68..ea7e890e7 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -1828,7 +1828,6 @@ class SQLCompiler(Compiled): result_expr = _CompileLabel( col_expr, name, alt_names=(column._key_label,) ) - elif ( asfrom and isinstance(column, elements.ColumnClause) @@ -1897,6 +1896,7 @@ class SQLCompiler(Compiled): """ cloned = {} column_translate = [{}] + created = set() def visit(element, **kw): if element in column_translate[-1]: @@ -1906,7 +1906,6 @@ class SQLCompiler(Compiled): return cloned[element] newelem = cloned[element] = element._clone() - if ( newelem._is_from_clause and newelem._is_join @@ -1921,6 +1920,8 @@ class SQLCompiler(Compiled): selectable_ = selectable.Select( [right.element], use_labels=True ).alias() + created.add(selectable_) + created.update(selectable_.c) for c in selectable_.c: c._key_label = c.key @@ -1971,6 +1972,11 @@ class SQLCompiler(Compiled): if barrier_select: column_translate.append({}) kw["transform_clue"] = "inside_select" + if not newelem._is_select_container: + froms = newelem.froms + newelem._raw_columns = list(newelem.selected_columns) + newelem._from_obj.update(froms) + newelem._reset_memoizations() newelem._copy_internals(clone=visit, **kw) if barrier_select: del column_translate[-1] @@ -1984,17 +1990,33 @@ class SQLCompiler(Compiled): def _transform_result_map_for_nested_joins( self, select, transformed_select ): - inner_col = dict( - (c._key_label, c) for c in transformed_select.inner_columns - ) - - d = dict((inner_col[c._key_label], c) for c in select.inner_columns) - - self._result_columns = [ - (key, name, tuple([d.get(col, col) for col in objs]), typ) - for key, name, objs, typ in self._result_columns + self._result_columns[:] = [ + result_rec + if col is tcol + else ( + result_rec[0], + name, + tuple([col if obj is tcol else obj for obj in result_rec[2]]), + result_rec[3], + ) + for result_rec, (name, col), (tname, tcol) in zip( + self._result_columns, + select._columns_plus_names, + transformed_select._columns_plus_names, + ) ] + # TODO: it's not anticipated that we need to correct anon_map + # however if we do, this is what it looks like: + # for (name, col), (tname, tcol) in zip( + # select._columns_plus_names, + # transformed_select._columns_plus_names, + # ): + # if isinstance(name, elements._anonymous_label) and name != tname: + # m1 = re.match(r"^%\((\d+ .+?)\)s$", name) + # m2 = re.match(r"^%\((\d+ .+?)\)s$", tname) + # self.anon_map[m1.group(1)] = self.anon_map[m2.group(1)] + _default_stack_entry = util.immutabledict( [("correlate_froms", frozenset()), ("asfrom_froms", frozenset())] ) diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index 5a9be7c62..66e92a63c 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -48,8 +48,9 @@ class UpdateBase( named_with_column = False def _generate_fromclause_column_proxies(self, fromclause): - for col in self._returning: - col._make_proxy(fromclause) + fromclause._columns._populate_separate_keys( + col._make_proxy(fromclause) for col in self._returning + ) def _process_colparams(self, parameters): def process_single(p): diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 5b4442222..735a125d7 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -184,6 +184,7 @@ class ClauseElement(roles.SQLRole, Visitable): _is_returns_rows = False _is_text_clause = False _is_from_container = False + _is_select_container = False _is_select_statement = False _order_by_label_element = None @@ -856,8 +857,7 @@ class ColumnElement( co._proxies = [self] if selectable._is_clone_of is not None: co._is_clone_of = selectable._is_clone_of.columns.get(key) - selectable._columns[key] = co - return co + return key, co def cast(self, type_): """Produce a type cast, i.e. ``CAST(<expression> AS <type>)``. @@ -887,6 +887,12 @@ class ColumnElement( """ return Label(name, self, self.type) + def _anon_label(self, seed): + while self._is_clone_of is not None: + self = self._is_clone_of + + return _anonymous_label("%%(%d %s)s" % (id(self), seed or "anon")) + @util.memoized_property def anon_label(self): """provides a constant 'anonymous label' for this ColumnElement. @@ -901,12 +907,11 @@ class ColumnElement( expressions and function calls. """ - while self._is_clone_of is not None: - self = self._is_clone_of + return self._anon_label(getattr(self, "name", None)) - return _anonymous_label( - "%%(%d %s)s" % (id(self), getattr(self, "name", "anon")) - ) + @util.memoized_property + def _label_anon_label(self): + return self._anon_label(getattr(self, "_label", None)) class BindParameter(roles.InElementRole, ColumnElement): @@ -3951,7 +3956,7 @@ class Label(roles.LabeledColumnExprRole, ColumnElement): return self.element._from_objects def _make_proxy(self, selectable, name=None, **kw): - e = self.element._make_proxy( + key, e = self.element._make_proxy( selectable, name=name if name else self.name, disallow_is_literal=True, @@ -3959,7 +3964,7 @@ class Label(roles.LabeledColumnExprRole, ColumnElement): e._proxies.append(self) if self._type is not None: e.type = self._type - return e + return key, e class ColumnClause(roles.LabeledColumnExprRole, Immutable, ColumnElement): @@ -4214,7 +4219,6 @@ class ColumnClause(roles.LabeledColumnExprRole, Immutable, ColumnElement): self, selectable, name=None, - attach=True, name_is_truncatable=False, disallow_is_literal=False, **kw @@ -4249,9 +4253,7 @@ class ColumnClause(roles.LabeledColumnExprRole, Immutable, ColumnElement): if selectable._is_clone_of is not None: c._is_clone_of = selectable._is_clone_of.columns.get(c.key) - if attach: - selectable._columns[c.key] = c - return c + return c.key, c class CollationClause(ColumnElement): diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index 04fb16a80..2feb6fd5f 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -118,7 +118,8 @@ class FunctionElement(Executable, ColumnElement, FromClause): """ - return ColumnCollection(self.label(None)) + col = self.label(None) + return ColumnCollection(columns=[(col.key, col)]) @util.memoized_property def clauses(self): diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index d39bc9832..23c58dc4e 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -40,7 +40,7 @@ from . import roles from . import type_api from . import visitors from .base import _bind_or_error -from .base import ColumnCollection +from .base import DedupeColumnCollection from .base import DialectKWArgs from .base import SchemaEventTarget from .coercions import _document_text_coercion @@ -538,7 +538,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause): self.indexes = set() self.constraints = set() - self._columns = ColumnCollection() + self._columns = DedupeColumnCollection() PrimaryKeyConstraint( _implicit_generated=True )._set_parent_with_dispatch(self) @@ -1607,13 +1607,13 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): ) c.table = selectable - selectable._columns.add(c) if selectable._is_clone_of is not None: c._is_clone_of = selectable._is_clone_of.columns[c.key] if self.primary_key: selectable.primary_key.add(c) - c.dispatch.after_parent_attach(c, selectable) - return c + if fk: + selectable.foreign_keys.update(fk) + return c.key, c def get_children(self, schema_visitor=False, **kwargs): if schema_visitor: @@ -1983,19 +1983,20 @@ class ForeignKey(DialectKWArgs, SchemaItem): self._set_target_column(_column) def _set_target_column(self, column): + assert isinstance(self.parent.table, Table) + # propagate TypeEngine to parent if it didn't have one if self.parent.type._isnull: self.parent.type = column.type # super-edgy case, if other FKs point to our column, # they'd get the type propagated out also. - if isinstance(self.parent.table, Table): - def set_type(fk): - if fk.parent.type._isnull: - fk.parent.type = column.type + def set_type(fk): + if fk.parent.type._isnull: + fk.parent.type = column.type - self.parent._setup_on_memoized_fks(set_type) + self.parent._setup_on_memoized_fks(set_type) self.column = column @@ -2072,7 +2073,8 @@ class ForeignKey(DialectKWArgs, SchemaItem): def _set_table(self, column, table): # standalone ForeignKey - create ForeignKeyConstraint # on the hosting Table when attached to the Table. - if self.constraint is None and isinstance(table, Table): + assert isinstance(table, Table) + if self.constraint is None: self.constraint = ForeignKeyConstraint( [], [], @@ -2088,7 +2090,6 @@ class ForeignKey(DialectKWArgs, SchemaItem): self.constraint._append_element(column, self) self.constraint._set_parent_with_dispatch(table) table.foreign_keys.add(self) - # set up remote ".column" attribute, or a note to pick it # up when the other Table/Column shows up if isinstance(self._colspec, util.string_types): @@ -2760,7 +2761,7 @@ class ColumnCollectionMixin(object): def __init__(self, *columns, **kw): _autoattach = kw.pop("_autoattach", True) self._column_flag = kw.pop("_column_flag", False) - self.columns = ColumnCollection() + self.columns = DedupeColumnCollection() self._pending_colargs = [ _to_schema_column_or_string(c) for c in columns ] @@ -2885,14 +2886,10 @@ class ColumnCollectionConstraint(ColumnCollectionMixin, Constraint): return self.columns.contains_column(col) def __iter__(self): - # inlining of - # return iter(self.columns) - # ColumnCollection->OrderedProperties->OrderedDict - ordered_dict = self.columns._data - return (ordered_dict[key] for key in ordered_dict._list) + return iter(self.columns) def __len__(self): - return len(self.columns._data) + return len(self.columns) class CheckConstraint(ColumnCollectionConstraint): @@ -3368,11 +3365,7 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): table.constraints.add(self) table_pks = [c for c in table.c if c.primary_key] - if ( - self.columns - and table_pks - and set(table_pks) != set(self.columns.values()) - ): + if self.columns and table_pks and set(table_pks) != set(self.columns): util.warn( "Table '%s' specifies columns %s as primary_key=True, " "not matching locally specified columns %s; setting the " @@ -3390,7 +3383,8 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): for c in self.columns: c.primary_key = True c.nullable = False - self.columns.extend(table_pks) + if table_pks: + self.columns.extend(table_pks) def _reload(self, columns): """repopulate this :class:`.PrimaryKeyConstraint` given diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index c93de8d73..10643c9e4 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -27,10 +27,10 @@ from .base import _from_objects from .base import _generative from .base import ColumnCollection from .base import ColumnSet +from .base import DedupeColumnCollection from .base import Executable from .base import Generative from .base import Immutable -from .base import SeparateKeyColumnCollection from .coercions import _document_text_coercion from .elements import _anonymous_label from .elements import _select_iterables @@ -534,8 +534,9 @@ class FromClause(roles.AnonymizedFromClauseRole, Selectable): self._memoized_property.expire_instance(self) def _generate_fromclause_column_proxies(self, fromclause): - for col in self.c: - col._make_proxy(fromclause) + fromclause._columns._populate_separate_keys( + col._make_proxy(fromclause) for col in self.c + ) @property def exported_columns(self): @@ -791,7 +792,9 @@ class Join(FromClause): (c for c in columns if c.primary_key), self.onclause ) ) - self._columns.update((col._key_label, col) for col in columns) + self._columns._populate_separate_keys( + (col._key_label, col) for col in columns + ) self.foreign_keys.update( itertools.chain(*[col.foreign_keys for col in columns]) ) @@ -1861,7 +1864,7 @@ class TableClause(Immutable, FromClause): super(TableClause, self).__init__() self.name = self.fullname = name - self._columns = ColumnCollection() + self._columns = DedupeColumnCollection() self.primary_key = ColumnSet() self.foreign_keys = set() for c in columns: @@ -1881,7 +1884,7 @@ class TableClause(Immutable, FromClause): return self.name.encode("ascii", "backslashreplace") def append_column(self, c): - self._columns[c.key] = c + self._columns.add(c) c.table = self def get_children(self, column_collections=True, **kwargs): @@ -2328,6 +2331,8 @@ class SelectStatementGrouping(GroupedElement, SelectBase): __visit_name__ = "grouping" + _is_select_container = True + def __init__(self, element): # type: (SelectBase) self.element = coercions.expect(roles.SelectStatementRole, element) @@ -2526,6 +2531,7 @@ class GenerativeSelect(SelectBase): FROM clauses to produce a unique set of column names regardless of name conflicts among the individual FROM clauses. + """ self.use_labels = True @@ -4081,6 +4087,8 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): """ names = set() + cols = _select_iterables(self._raw_columns) + def name_for_col(c): # we use key_label since this name is intended for targeting # within the ColumnCollection only, it's not related to SQL @@ -4090,18 +4098,22 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): else: name = c._proxy_key if name in names: - name = c.anon_label + if self.use_labels: + name = c._label_anon_label + else: + name = c.anon_label else: names.add(name) return name - return SeparateKeyColumnCollection( - (name_for_col(c), c) - for c in util.unique_list(_select_iterables(self._raw_columns)) + return ColumnCollection( + (name_for_col(c), c) for c in cols ).as_immutable() @_memoized_property def _columns_plus_names(self): + cols = _select_iterables(self._raw_columns) + if self.use_labels: names = set() @@ -4111,23 +4123,18 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): name = c._label if name in names: - name = c.anon_label + name = c._label_anon_label else: names.add(name) return name, c - return [ - name_for_col(c) - for c in util.unique_list(_select_iterables(self._raw_columns)) - ] + return [name_for_col(c) for c in cols] else: - return [ - (None, c) - for c in util.unique_list(_select_iterables(self._raw_columns)) - ] + return [(None, c) for c in cols] def _generate_fromclause_column_proxies(self, subquery): keys_seen = set() + prox = [] for name, c in self._columns_plus_names: if not hasattr(c, "_make_proxy"): @@ -4137,14 +4144,16 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): elif self.use_labels: key = c._key_label if key is not None and key in keys_seen: - key = c.anon_label + key = c._label_anon_label keys_seen.add(key) else: key = None - - c._make_proxy( - subquery, key=key, name=name, name_is_truncatable=True + prox.append( + c._make_proxy( + subquery, key=key, name=name, name_is_truncatable=True + ) ) + subquery._columns._populate_separate_keys(prox) def _needs_parens_for_grouping(self): return ( @@ -4397,7 +4406,9 @@ class TextualSelect(SelectBase): .. versionadded:: 1.4 """ - return ColumnCollection(*self.column_args).as_immutable() + return ColumnCollection( + (c.key, c) for c in self.column_args + ).as_immutable() @property def _bind(self): @@ -4408,8 +4419,9 @@ class TextualSelect(SelectBase): self.element = self.element.bindparams(*binds, **bind_as_values) def _generate_fromclause_column_proxies(self, fromclause): - for c in self.column_args: - c._make_proxy(fromclause) + fromclause._columns._populate_separate_keys( + c._make_proxy(fromclause) for c in self.column_args + ) def _copy_internals(self, clone=_clone, **kw): self._reset_memoizations() diff --git a/test/base/test_utils.py b/test/base/test_utils.py index d7e4deb28..4f073ebfe 100644 --- a/test/base/test_utils.py +++ b/test/base/test_utils.py @@ -9,7 +9,7 @@ from sqlalchemy import sql from sqlalchemy import testing from sqlalchemy import util from sqlalchemy.sql import column -from sqlalchemy.sql.base import SeparateKeyColumnCollection +from sqlalchemy.sql.base import DedupeColumnCollection from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import eq_ @@ -18,6 +18,8 @@ from sqlalchemy.testing import fails_if from sqlalchemy.testing import fixtures from sqlalchemy.testing import in_ from sqlalchemy.testing import is_ +from sqlalchemy.testing import is_false +from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing import ne_ from sqlalchemy.testing.util import gc_collect @@ -442,60 +444,110 @@ class ToListTest(fixtures.TestBase): ) -class SeparateKeysColumnCollectionTest( - testing.AssertsCompiledSQL, fixtures.TestBase -): - def test_in(self): - cc = SeparateKeyColumnCollection() - cc["kcol1"] = sql.column("col1") - cc["kcol2"] = sql.column("col2") - cc["kcol3"] = sql.column("col3") - assert "col1" not in cc - assert "kcol2" in cc +class ColumnCollectionCommon(testing.AssertsCompiledSQL): + def _assert_collection_integrity(self, coll): + eq_(coll._colset, set(c for k, c in coll._collection)) + d = {} + for k, col in coll._collection: + d.setdefault(k, col) + d.update({idx: col for idx, (k, col) in enumerate(coll._collection)}) + eq_(coll._index, d) + + def test_keys(self): + c1, c2, c3 = sql.column("c1"), sql.column("c2"), sql.column("c3") + c2.key = "foo" + cc = self._column_collection( + columns=[("c1", c1), ("foo", c2), ("c3", c3)] + ) + eq_(cc.keys(), ["c1", "foo", "c3"]) - def test_get(self): - c1, c2 = sql.column("col1"), sql.column("col2") - cc = SeparateKeyColumnCollection([("kcol1", c1), ("kcol2", c2)]) - is_(cc.kcol1, c1) - is_(cc.kcol2, c2) + ci = cc.as_immutable() + eq_(ci.keys(), ["c1", "foo", "c3"]) + + def test_key_index_error(self): + cc = self._column_collection( + columns=[ + ("col1", sql.column("col1")), + ("col2", sql.column("col2")), + ] + ) + assert_raises(KeyError, lambda: cc["foo"]) + assert_raises(KeyError, lambda: cc[object()]) + assert_raises(IndexError, lambda: cc[5]) - def test_all_cols(self): - c1, c2 = sql.column("col1"), sql.column("col2") - cc = SeparateKeyColumnCollection([("kcol1", c1), ("kcol2", c2)]) - eq_(cc._all_columns, [c1, c2]) + def test_contains_column(self): + c1, c2, c3 = sql.column("c1"), sql.column("c2"), sql.column("c3") + cc = self._column_collection(columns=[("c1", c1), ("c2", c2)]) + is_true(cc.contains_column(c1)) + is_false(cc.contains_column(c3)) -class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): def test_in(self): - cc = sql.ColumnCollection() - cc.add(sql.column("col1")) - cc.add(sql.column("col2")) - cc.add(sql.column("col3")) + col1 = sql.column("col1") + cc = self._column_collection( + columns=[ + ("col1", col1), + ("col2", sql.column("col2")), + ("col3", sql.column("col3")), + ] + ) assert "col1" in cc assert "col2" in cc - try: - cc["col1"] in cc - assert False - except exc.ArgumentError as e: - eq_(str(e), "__contains__ requires a string argument") + assert_raises_message( + exc.ArgumentError, + "__contains__ requires a string argument", + lambda: col1 in cc, + ) def test_compare(self): - cc1 = sql.ColumnCollection() - cc2 = sql.ColumnCollection() - cc3 = sql.ColumnCollection() c1 = sql.column("col1") c2 = c1.label("col2") c3 = sql.column("col3") - cc1.add(c1) - cc2.add(c2) - cc3.add(c3) - assert (cc1 == cc2).compare(c1 == c2) - assert not (cc1 == cc3).compare(c2 == c3) - @testing.emits_warning("Column ") + is_true( + self._column_collection( + [("col1", c1), ("col2", c2), ("col3", c3)] + ).compare( + self._column_collection( + [("col1", c1), ("col2", c2), ("col3", c3)] + ) + ) + ) + is_false( + self._column_collection( + [("col1", c1), ("col2", c2), ("col3", c3)] + ).compare(self._column_collection([("col1", c1), ("col2", c2)])) + ) + + +class ColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): + def _column_collection(self, columns=None): + return sql.ColumnCollection(columns=columns) + + def test_separate_key_all_cols(self): + c1, c2 = sql.column("col1"), sql.column("col2") + cc = self._column_collection([("kcol1", c1), ("kcol2", c2)]) + eq_(cc._all_columns, [c1, c2]) + + def test_separate_key_get(self): + c1, c2 = sql.column("col1"), sql.column("col2") + cc = self._column_collection([("kcol1", c1), ("kcol2", c2)]) + is_(cc.kcol1, c1) + is_(cc.kcol2, c2) + + def test_separate_key_in(self): + cc = self._column_collection( + columns=[ + ("kcol1", sql.column("col1")), + ("kcol2", sql.column("col2")), + ("kcol3", sql.column("col3")), + ] + ) + assert "col1" not in cc + assert "kcol2" in cc + def test_dupes_add(self): - cc = sql.ColumnCollection() c1, c2a, c3, c2b = ( column("c1"), @@ -504,27 +556,198 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): column("c2"), ) + cc = sql.ColumnCollection() + cc.add(c1) - cc.add(c2a) + cc.add(c2a, "c2") cc.add(c3) cc.add(c2b) eq_(cc._all_columns, [c1, c2a, c3, c2b]) + eq_(list(cc), [c1, c2a, c3, c2b]) + eq_(cc.keys(), ["c1", "c2", "c3", "c2"]) + + assert cc.contains_column(c2a) + assert cc.contains_column(c2b) + + # this is deterministic + is_(cc["c2"], c2a) + + self._assert_collection_integrity(cc) + + ci = cc.as_immutable() + eq_(ci._all_columns, [c1, c2a, c3, c2b]) + eq_(list(ci), [c1, c2a, c3, c2b]) + eq_(ci.keys(), ["c1", "c2", "c3", "c2"]) + + def test_dupes_construct(self): + + c1, c2a, c3, c2b = ( + column("c1"), + column("c2"), + column("c3"), + column("c2"), + ) + + cc = sql.ColumnCollection( + columns=[("c1", c1), ("c2", c2a), ("c3", c3), ("c2", c2b)] + ) + + eq_(cc._all_columns, [c1, c2a, c3, c2b]) + + eq_(list(cc), [c1, c2a, c3, c2b]) + eq_(cc.keys(), ["c1", "c2", "c3", "c2"]) + + assert cc.contains_column(c2a) + assert cc.contains_column(c2b) + + # this is deterministic + is_(cc["c2"], c2a) + + self._assert_collection_integrity(cc) + + ci = cc.as_immutable() + eq_(ci._all_columns, [c1, c2a, c3, c2b]) + eq_(list(ci), [c1, c2a, c3, c2b]) + eq_(ci.keys(), ["c1", "c2", "c3", "c2"]) + + def test_identical_dupe_construct(self): + + c1, c2, c3 = (column("c1"), column("c2"), column("c3")) + + cc = sql.ColumnCollection( + columns=[("c1", c1), ("c2", c2), ("c3", c3), ("c2", c2)] + ) + + eq_(cc._all_columns, [c1, c2, c3, c2]) + # for iter, c2a is replaced by c2b, ordering # is maintained in that way. ideally, iter would be # the same as the "_all_columns" collection. + eq_(list(cc), [c1, c2, c3, c2]) + + assert cc.contains_column(c2) + self._assert_collection_integrity(cc) + + ci = cc.as_immutable() + eq_(ci._all_columns, [c1, c2, c3, c2]) + eq_(list(ci), [c1, c2, c3, c2]) + + +class DedupeColumnCollectionTest(ColumnCollectionCommon, fixtures.TestBase): + def _column_collection(self, columns=None): + return DedupeColumnCollection(columns=columns) + + def test_separate_key_cols(self): + c1, c2 = sql.column("col1"), sql.column("col2") + assert_raises_message( + exc.ArgumentError, + "DedupeColumnCollection requires columns be under " + "the same key as their .key", + self._column_collection, + [("kcol1", c1), ("kcol2", c2)], + ) + + cc = self._column_collection() + assert_raises_message( + exc.ArgumentError, + "DedupeColumnCollection requires columns be under " + "the same key as their .key", + cc.add, + c1, + "kcol1", + ) + + def test_pickle_w_mutation(self): + c1, c2, c3 = sql.column("c1"), sql.column("c2"), sql.column("c3") + + c2.key = "foo" + + cc = self._column_collection(columns=[("c1", c1), ("foo", c2)]) + ci = cc.as_immutable() + + d = {"cc": cc, "ci": ci} + + for loads, dumps in picklers(): + dp = loads(dumps(d)) + + cp = dp["cc"] + cpi = dp["ci"] + self._assert_collection_integrity(cp) + self._assert_collection_integrity(cpi) + + assert cp._colset is cpi._colset + assert cp._index is cpi._index + assert cp._collection is cpi._collection + + cp.add(c3) + + eq_(cp.keys(), ["c1", "foo", "c3"]) + eq_(cpi.keys(), ["c1", "foo", "c3"]) + + assert cp.contains_column(c3) + assert cpi.contains_column(c3) + + def test_keys_after_replace(self): + c1, c2, c3 = sql.column("c1"), sql.column("c2"), sql.column("c3") + c2.key = "foo" + cc = self._column_collection( + columns=[("c1", c1), ("foo", c2), ("c3", c3)] + ) + eq_(cc.keys(), ["c1", "foo", "c3"]) + + c4 = sql.column("c3") + cc.replace(c4) + eq_(cc.keys(), ["c1", "foo", "c3"]) + self._assert_collection_integrity(cc) + + def test_dupes_add_dedupe(self): + cc = DedupeColumnCollection() + + c1, c2a, c3, c2b = ( + column("c1"), + column("c2"), + column("c3"), + column("c2"), + ) + + cc.add(c1) + cc.add(c2a) + cc.add(c3) + cc.add(c2b) + + eq_(cc._all_columns, [c1, c2b, c3]) + eq_(list(cc), [c1, c2b, c3]) - assert cc.contains_column(c2a) + assert not cc.contains_column(c2a) assert cc.contains_column(c2b) + self._assert_collection_integrity(cc) - ci = cc.as_immutable() - eq_(ci._all_columns, [c1, c2a, c3, c2b]) - eq_(list(ci), [c1, c2b, c3]) + def test_dupes_construct_dedupe(self): - def test_identical_dupe_add(self): - cc = sql.ColumnCollection() + c1, c2a, c3, c2b = ( + column("c1"), + column("c2"), + column("c3"), + column("c2"), + ) + + cc = DedupeColumnCollection( + columns=[("c1", c1), ("c2", c2a), ("c3", c3), ("c2", c2b)] + ) + + eq_(cc._all_columns, [c1, c2b, c3]) + + eq_(list(cc), [c1, c2b, c3]) + + assert not cc.contains_column(c2a) + assert cc.contains_column(c2b) + self._assert_collection_integrity(cc) + + def test_identical_dupe_add_dedupes(self): + cc = DedupeColumnCollection() c1, c2, c3 = (column("c1"), column("c2"), column("c3")) @@ -535,27 +758,43 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): eq_(cc._all_columns, [c1, c2, c3]) - self.assert_compile( - cc == [c1, c2, c3], "c1 = c1 AND c2 = c2 AND c3 = c3" - ) - # for iter, c2a is replaced by c2b, ordering # is maintained in that way. ideally, iter would be # the same as the "_all_columns" collection. eq_(list(cc), [c1, c2, c3]) assert cc.contains_column(c2) + self._assert_collection_integrity(cc) ci = cc.as_immutable() eq_(ci._all_columns, [c1, c2, c3]) eq_(list(ci), [c1, c2, c3]) - self.assert_compile( - ci == [c1, c2, c3], "c1 = c1 AND c2 = c2 AND c3 = c3" + def test_identical_dupe_construct_dedupes(self): + + c1, c2, c3 = (column("c1"), column("c2"), column("c3")) + + cc = DedupeColumnCollection( + columns=[("c1", c1), ("c2", c2), ("c3", c3), ("c2", c2)] ) + eq_(cc._all_columns, [c1, c2, c3]) + + # for iter, c2a is replaced by c2b, ordering + # is maintained in that way. ideally, iter would be + # the same as the "_all_columns" collection. + eq_(list(cc), [c1, c2, c3]) + + assert cc.contains_column(c2) + self._assert_collection_integrity(cc) + + ci = cc.as_immutable() + eq_(ci._all_columns, [c1, c2, c3]) + eq_(list(ci), [c1, c2, c3]) + def test_replace(self): - cc = sql.ColumnCollection() + cc = DedupeColumnCollection() + ci = cc.as_immutable() c1, c2a, c3, c2b = ( column("c1"), @@ -572,16 +811,49 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): eq_(cc._all_columns, [c1, c2b, c3]) eq_(list(cc), [c1, c2b, c3]) + is_(cc[1], c2b) assert not cc.contains_column(c2a) assert cc.contains_column(c2b) + self._assert_collection_integrity(cc) + eq_(ci._all_columns, [c1, c2b, c3]) + eq_(list(ci), [c1, c2b, c3]) + is_(ci[1], c2b) + + def test_replace_key_matches_name_of_another(self): + cc = DedupeColumnCollection() ci = cc.as_immutable() + + c1, c2a, c3, c2b = ( + column("c1"), + column("c2"), + column("c3"), + column("c4"), + ) + c2b.key = "c2" + + cc.add(c1) + cc.add(c2a) + cc.add(c3) + + cc.replace(c2b) + + eq_(cc._all_columns, [c1, c2b, c3]) + eq_(list(cc), [c1, c2b, c3]) + is_(cc[1], c2b) + self._assert_collection_integrity(cc) + + assert not cc.contains_column(c2a) + assert cc.contains_column(c2b) + eq_(ci._all_columns, [c1, c2b, c3]) eq_(list(ci), [c1, c2b, c3]) + is_(ci[1], c2b) def test_replace_key_matches(self): - cc = sql.ColumnCollection() + cc = DedupeColumnCollection() + ci = cc.as_immutable() c1, c2a, c3, c2b = ( column("c1"), @@ -599,16 +871,21 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): assert not cc.contains_column(c2a) assert cc.contains_column(c2b) + is_(cc[1], c2b) + assert_raises(IndexError, lambda: cc[3]) + self._assert_collection_integrity(cc) eq_(cc._all_columns, [c1, c2b, c3]) eq_(list(cc), [c1, c2b, c3]) - ci = cc.as_immutable() eq_(ci._all_columns, [c1, c2b, c3]) eq_(list(ci), [c1, c2b, c3]) + is_(ci[1], c2b) + assert_raises(IndexError, lambda: ci[3]) def test_replace_name_matches(self): - cc = sql.ColumnCollection() + cc = DedupeColumnCollection() + ci = cc.as_immutable() c1, c2a, c3, c2b = ( column("c1"), @@ -628,14 +905,19 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): assert cc.contains_column(c2b) eq_(cc._all_columns, [c1, c2b, c3]) - eq_(list(cc), [c1, c3, c2b]) + eq_(list(cc), [c1, c2b, c3]) + eq_(len(cc), 3) + is_(cc[1], c2b) + self._assert_collection_integrity(cc) - ci = cc.as_immutable() eq_(ci._all_columns, [c1, c2b, c3]) - eq_(list(ci), [c1, c3, c2b]) + eq_(list(ci), [c1, c2b, c3]) + eq_(len(ci), 3) + is_(ci[1], c2b) def test_replace_no_match(self): - cc = sql.ColumnCollection() + cc = DedupeColumnCollection() + ci = cc.as_immutable() c1, c2, c3, c4 = column("c1"), column("c2"), column("c3"), column("c4") c4.key = "X" @@ -651,42 +933,102 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): eq_(cc._all_columns, [c1, c2, c3, c4]) eq_(list(cc), [c1, c2, c3, c4]) + is_(cc[3], c4) + self._assert_collection_integrity(cc) - ci = cc.as_immutable() eq_(ci._all_columns, [c1, c2, c3, c4]) eq_(list(ci), [c1, c2, c3, c4]) + is_(ci[3], c4) - def test_dupes_extend(self): - cc = sql.ColumnCollection() + def test_replace_switch_key_name(self): + c1 = column("id") + c2 = column("street") + c3 = column("user_id") - c1, c2a, c3, c2b = ( - column("c1"), - column("c2"), - column("c3"), - column("c2"), + cc = DedupeColumnCollection( + columns=[("id", c1), ("street", c2), ("user_id", c3)] ) - cc.add(c1) - cc.add(c2a) + # for replace col with different key than name, it necessarily + # removes two columns - cc.extend([c3, c2b]) + c4 = column("id") + c4.key = "street" - eq_(cc._all_columns, [c1, c2a, c3, c2b]) + cc.replace(c4) - # for iter, c2a is replaced by c2b, ordering - # is maintained in that way. ideally, iter would be - # the same as the "_all_columns" collection. - eq_(list(cc), [c1, c2b, c3]) + eq_(list(cc), [c4, c3]) + self._assert_collection_integrity(cc) - assert cc.contains_column(c2a) - assert cc.contains_column(c2b) + def test_remove(self): + + c1, c2, c3 = column("c1"), column("c2"), column("c3") + cc = DedupeColumnCollection( + columns=[("c1", c1), ("c2", c2), ("c3", c3)] + ) ci = cc.as_immutable() - eq_(ci._all_columns, [c1, c2a, c3, c2b]) - eq_(list(ci), [c1, c2b, c3]) - def test_dupes_update(self): - cc = sql.ColumnCollection() + eq_(cc._all_columns, [c1, c2, c3]) + eq_(list(cc), [c1, c2, c3]) + assert cc.contains_column(c2) + assert "c2" in cc + + eq_(ci._all_columns, [c1, c2, c3]) + eq_(list(ci), [c1, c2, c3]) + assert ci.contains_column(c2) + assert "c2" in ci + + cc.remove(c2) + + eq_(cc._all_columns, [c1, c3]) + eq_(list(cc), [c1, c3]) + is_(cc[0], c1) + is_(cc[1], c3) + assert not cc.contains_column(c2) + assert "c2" not in cc + self._assert_collection_integrity(cc) + + eq_(ci._all_columns, [c1, c3]) + eq_(list(ci), [c1, c3]) + is_(ci[0], c1) + is_(ci[1], c3) + assert not ci.contains_column(c2) + assert "c2" not in ci + + assert_raises(IndexError, lambda: ci[2]) + + def test_remove_doesnt_change_iteration(self): + + c1, c2, c3, c4, c5 = ( + column("c1"), + column("c2"), + column("c3"), + column("c4"), + column("c5"), + ) + + cc = DedupeColumnCollection( + columns=[ + ("c1", c1), + ("c2", c2), + ("c3", c3), + ("c4", c4), + ("c5", c5), + ] + ) + + for col in cc: + if col.name not in ["c1", "c2"]: + cc.remove(col) + + eq_(cc.keys(), ["c1", "c2"]) + eq_([c.name for c in cc], ["c1", "c2"]) + self._assert_collection_integrity(cc) + + def test_dupes_extend(self): + cc = DedupeColumnCollection() + ci = cc.as_immutable() c1, c2a, c3, c2b = ( column("c1"), @@ -698,20 +1040,29 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): cc.add(c1) cc.add(c2a) - cc.update([(c3.key, c3), (c2b.key, c2b)]) + cc.extend([c3, c2b]) # this should remove c2a - eq_(cc._all_columns, [c1, c2a, c3, c2b]) + eq_(cc._all_columns, [c1, c2b, c3]) + eq_(list(cc), [c1, c2b, c3]) + is_(cc[1], c2b) + is_(cc[2], c3) + assert_raises(IndexError, lambda: cc[3]) + self._assert_collection_integrity(cc) - assert cc.contains_column(c2a) + assert not cc.contains_column(c2a) assert cc.contains_column(c2b) - # for iter, c2a is replaced by c2b, ordering - # is maintained in that way. ideally, iter would be - # the same as the "_all_columns" collection. - eq_(list(cc), [c1, c2b, c3]) + eq_(ci._all_columns, [c1, c2b, c3]) + eq_(list(ci), [c1, c2b, c3]) + is_(ci[1], c2b) + is_(ci[2], c3) + assert_raises(IndexError, lambda: ci[3]) - def test_extend_existing(self): - cc = sql.ColumnCollection() + assert not ci.contains_column(c2a) + assert ci.contains_column(c2b) + + def test_extend_existing_maintains_ordering(self): + cc = DedupeColumnCollection() c1, c2, c3, c4, c5 = ( column("c1"), @@ -723,32 +1074,16 @@ class ColumnCollectionTest(testing.AssertsCompiledSQL, fixtures.TestBase): cc.extend([c1, c2]) eq_(cc._all_columns, [c1, c2]) + self._assert_collection_integrity(cc) cc.extend([c3]) eq_(cc._all_columns, [c1, c2, c3]) - cc.extend([c4, c2, c5]) + self._assert_collection_integrity(cc) - eq_(cc._all_columns, [c1, c2, c3, c4, c5]) - - def test_update_existing(self): - cc = sql.ColumnCollection() - - c1, c2, c3, c4, c5 = ( - column("c1"), - column("c2"), - column("c3"), - column("c4"), - column("c5"), - ) - - cc.update([("c1", c1), ("c2", c2)]) - eq_(cc._all_columns, [c1, c2]) - - cc.update([("c3", c3)]) - eq_(cc._all_columns, [c1, c2, c3]) - cc.update([("c4", c4), ("c2", c2), ("c5", c5)]) + cc.extend([c4, c2, c5]) eq_(cc._all_columns, [c1, c2, c3, c4, c5]) + self._assert_collection_integrity(cc) class LRUTest(fixtures.TestBase): diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py index 1cabf8963..f6c19047e 100644 --- a/test/engine/test_reflection.py +++ b/test/engine/test_reflection.py @@ -280,6 +280,7 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): # test against a table which is already reflected meta3 = MetaData(testing.db) foo = Table("foo", meta3, autoload=True) + foo = Table( "foo", meta3, include_columns=["b", "f", "e"], extend_existing=True ) @@ -308,7 +309,7 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): old_y = Column("y", String) old_q = Column("q", Integer) t2 = Table("t", m2, old_z, old_q) - eq_(t2.primary_key.columns, (t2.c.z,)) + eq_(list(t2.primary_key.columns), [t2.c.z]) t2 = Table( "t", m2, @@ -318,7 +319,11 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): autoload_with=testing.db, ) eq_(set(t2.columns.keys()), set(["x", "y", "z", "q", "id"])) - eq_(t2.primary_key.columns, (t2.c.id,)) + + # this has been the actual behavior, the cols are added together, + # however the test wasn't checking this correctly + eq_(list(t2.primary_key.columns), [t2.c.z, t2.c.id]) + assert t2.c.z is not old_z assert t2.c.y is old_y assert t2.c.z.type._type_affinity is Integer @@ -340,7 +345,7 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): old_y = Column("y", String) old_q = Column("q", Integer) t4 = Table("t", m4, old_z, old_q) - eq_(t4.primary_key.columns, (t4.c.z,)) + eq_(list(t4.primary_key.columns), [t4.c.z]) t4 = Table( "t", m4, @@ -351,7 +356,7 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): autoload_with=testing.db, ) eq_(set(t4.columns.keys()), set(["x", "y", "z", "q", "id"])) - eq_(t4.primary_key.columns, (t4.c.id,)) + eq_(list(t4.primary_key.columns), [t4.c.z, t4.c.id]) assert t4.c.z is old_z assert t4.c.y is old_y assert t4.c.z.type._type_affinity is String @@ -770,6 +775,9 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): ), autoload=True, ) + + # for the thing happening here with the column collection, + # see test/base/test_utils.py-> test_replace_switch_key_name. assert u4.join(a4).onclause.compare(u4.c.u_id == a4.c.id) assert list(u4.primary_key) == [u4.c.u_id] assert len(u4.columns) == 2 diff --git a/test/profiles.txt b/test/profiles.txt index abdc79f96..469dac01c 100644 --- a/test/profiles.txt +++ b/test/profiles.txt @@ -21,20 +21,20 @@ test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_pymysql_dbapi test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_mysql_pymysql_dbapiunicode_nocextensions 70,70 test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_dbapiunicode_cextensions 70,70 test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 70,70 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_cextensions 70 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 70 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_cextensions 70 -test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 70 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_cextensions 69 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 69 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_cextensions 69 +test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 69 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_cextensions 73,73,73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_nocextensions 73,73,73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_pymysql_dbapiunicode_cextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_pymysql_dbapiunicode_nocextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_oracle_cx_oracle_dbapiunicode_cextensions 73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_cextensions 73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_cextensions 73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 73 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_cextensions 72 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 72 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_cextensions 72 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 72 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_select @@ -46,20 +46,20 @@ test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_pymysql_dbapi test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_mysql_pymysql_dbapiunicode_nocextensions 163,163 test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_dbapiunicode_cextensions 163,161 test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 163,161 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_cextensions 169 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 169 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_cextensions 169 -test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 169 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_cextensions 165 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 165 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_cextensions 165 +test.aaa_profiling.test_compiler.CompileTest.test_select 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 165 test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_mysqldb_dbapiunicode_cextensions 176,176,176,176 test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_mysqldb_dbapiunicode_nocextensions 176,176,176,176 test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_pymysql_dbapiunicode_cextensions 176,176 test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_mysql_pymysql_dbapiunicode_nocextensions 176,176 test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_oracle_cx_oracle_dbapiunicode_cextensions 176 test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 176 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_cextensions 182 -test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 182 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_cextensions 177 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 177 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_cextensions 177 +test.aaa_profiling.test_compiler.CompileTest.test_select 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 177 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_select_labels @@ -71,20 +71,20 @@ test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_pymysq test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_mysql_pymysql_dbapiunicode_nocextensions 196,196 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_dbapiunicode_cextensions 196,194 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 196,194 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_cextensions 202 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 202 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_cextensions 202 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 202 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_cextensions 198 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 198 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_cextensions 198 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 198 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_mysqldb_dbapiunicode_cextensions 209,209,209,209 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_mysqldb_dbapiunicode_nocextensions 209,209,209,209 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_pymysql_dbapiunicode_cextensions 209,209 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_mysql_pymysql_dbapiunicode_nocextensions 209,209 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_oracle_cx_oracle_dbapiunicode_cextensions 209 test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 209 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_cextensions 215 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 215 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_cextensions 215 -test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 215 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_cextensions 210 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 210 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_cextensions 210 +test.aaa_profiling.test_compiler.CompileTest.test_select_labels 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 210 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_update @@ -96,20 +96,20 @@ test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_pymysql_dbapi test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_mysql_pymysql_dbapiunicode_nocextensions 80,80 test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_dbapiunicode_cextensions 82,80 test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 82,80 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_cextensions 82 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 82 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_cextensions 82 -test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 82 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_cextensions 81 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 81 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_cextensions 81 +test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_cextensions 83,81,81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_nocextensions 83,81,81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_pymysql_dbapiunicode_cextensions 81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_pymysql_dbapiunicode_nocextensions 81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_oracle_cx_oracle_dbapiunicode_cextensions 83 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 83 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_cextensions 83 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 83 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_cextensions 83 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 83 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_cextensions 82 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 82 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_cextensions 82 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 82 # TEST: test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause @@ -121,93 +121,99 @@ test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_p test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_mysql_pymysql_dbapiunicode_nocextensions 158,158 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_dbapiunicode_cextensions 158,156 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 158,156 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_cextensions 161 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 161 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_cextensions 161 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 161 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_cextensions 160 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 160 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_cextensions 160 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 160 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_mysqldb_dbapiunicode_cextensions 158,158,158,158 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_mysqldb_dbapiunicode_nocextensions 158,158,158,158 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_pymysql_dbapiunicode_cextensions 158,158 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_mysql_pymysql_dbapiunicode_nocextensions 158,158 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_oracle_cx_oracle_dbapiunicode_cextensions 158 test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 158 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_cextensions 161 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 161 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_cextensions 161 -test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 161 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_cextensions 160 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 160 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_cextensions 160 +test.aaa_profiling.test_compiler.CompileTest.test_update_whereclause 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 160 # TEST: test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members -test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 4638 -test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 3.7_sqlite_pysqlite_dbapiunicode_cextensions 942 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 2.7_postgresql_psycopg2_dbapiunicode_cextensions 1324 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 1324 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1324 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1324 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 3.7_postgresql_psycopg2_dbapiunicode_cextensions 924 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 924 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 3.7_sqlite_pysqlite_dbapiunicode_cextensions 924 +test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_members 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 924 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_mysql_mysqldb_dbapiunicode_cextensions 51975 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_mysql_mysqldb_dbapiunicode_nocextensions 54975 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_oracle_cx_oracle_dbapiunicode_cextensions 52014 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 49599 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 52599 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 49185 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 52185 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 48598 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 51598 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 48184 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 51184 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_mysql_mysqldb_dbapiunicode_cextensions 54378 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_mysql_mysqldb_dbapiunicode_nocextensions 57978 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 57517 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 52502 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 55702 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 51596 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 54796 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 51501 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 54701 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 50995 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 53795 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_mysql_mysqldb_dbapiunicode_cextensions 51972 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_mysql_mysqldb_dbapiunicode_nocextensions 54972 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_oracle_cx_oracle_dbapiunicode_cextensions 51972 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 49572 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 52572 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 49156 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 52156 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 48572 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 51572 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_cextensions 48156 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 51156 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_mysql_mysqldb_dbapiunicode_cextensions 54364 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_mysql_mysqldb_dbapiunicode_nocextensions 57964 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 57464 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 52464 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 55664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 51556 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 54756 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 51464 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 54664 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_cextensions 50956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 53756 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_mysql_mysqldb_dbapiunicode_cextensions 49677 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_mysql_mysqldb_dbapiunicode_nocextensions 52677 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_oracle_cx_oracle_dbapiunicode_cextensions 49677 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 47277 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 50277 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46861 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 49861 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 46277 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 49277 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45861 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 48861 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_mysql_mysqldb_dbapiunicode_cextensions 51472 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_mysql_mysqldb_dbapiunicode_nocextensions 55072 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 54572 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 49572 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 52772 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 51864 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 48572 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 51772 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48064 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 50864 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_mysql_mysqldb_dbapiunicode_cextensions 49772 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_mysql_mysqldb_dbapiunicode_nocextensions 52772 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_oracle_cx_oracle_dbapiunicode_cextensions 49772 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 47372 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 50372 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46956 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 49956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 46372 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 49372 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 48956 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_mysql_mysqldb_dbapiunicode_cextensions 51564 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_mysql_mysqldb_dbapiunicode_nocextensions 55164 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 54664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 49664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 52864 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48756 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 51956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 48664 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 51864 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48156 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 50956 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle @@ -231,34 +237,34 @@ test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle 3.7_sqlite_pysq test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_mysql_mysqldb_dbapiunicode_cextensions 49677 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_mysql_mysqldb_dbapiunicode_nocextensions 52677 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_oracle_cx_oracle_dbapiunicode_cextensions 49677 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 47277 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 50277 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46861 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 49861 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 46277 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 49277 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45861 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 48861 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_mysql_mysqldb_dbapiunicode_cextensions 51472 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_mysql_mysqldb_dbapiunicode_nocextensions 55072 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 54572 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 49572 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 52772 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 51864 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 48572 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 51772 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48064 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 50864 # 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_mysql_mysqldb_dbapiunicode_cextensions 49772 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_mysql_mysqldb_dbapiunicode_nocextensions 52772 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_oracle_cx_oracle_dbapiunicode_cextensions 49772 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 47372 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 50372 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 46956 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 49956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_cextensions 46372 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 49372 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_cextensions 45956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 48956 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_mysql_mysqldb_dbapiunicode_cextensions 51564 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_mysql_mysqldb_dbapiunicode_nocextensions 55164 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 54664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 49664 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 52864 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48756 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 51956 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 48664 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 51864 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 48156 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 50956 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations @@ -274,7 +280,7 @@ test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 31009 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 28709 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 30409 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28001 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28401 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 29701 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations @@ -291,7 +297,7 @@ test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 31109 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_cextensions 28809 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 30509 -test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28101 +test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_cextensions 28501 test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 29801 # TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set @@ -388,18 +394,18 @@ test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_mysql_mysqldb_dba test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_mysql_mysqldb_dbapiunicode_nocextensions 26204 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_oracle_cx_oracle_dbapiunicode_cextensions 17299 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 44316 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_postgresql_psycopg2_dbapiunicode_cextensions 17216 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 26221 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_cextensions 17196 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 26201 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_postgresql_psycopg2_dbapiunicode_cextensions 17210 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 26215 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_cextensions 17190 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 26195 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_mysql_mysqldb_dbapiunicode_cextensions 18218 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_mysql_mysqldb_dbapiunicode_nocextensions 27225 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_oracle_cx_oracle_dbapiunicode_cextensions 18306 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 27313 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_postgresql_psycopg2_dbapiunicode_cextensions 18250 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 27257 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_cextensions 18223 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 27230 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_postgresql_psycopg2_dbapiunicode_cextensions 18244 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 27251 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_cextensions 18217 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 27224 # TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols @@ -424,62 +430,32 @@ test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols 3.7_sqlite_pys # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_mssql_pyodbc_dbapiunicode_cextensions 418033 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_mssql_pyodbc_dbapiunicode_nocextensions 418033 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_mysql_mysqldb_dbapiunicode_cextensions 419084 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_mysql_mysqldb_dbapiunicode_nocextensions 419094 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_oracle_cx_oracle_dbapiunicode_cextensions 418945 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 418945 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_postgresql_psycopg2_dbapiunicode_cextensions 439576 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 439581 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_cextensions 439566 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 439576 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_mysql_mysqldb_dbapiunicode_cextensions 455858 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_mysql_mysqldb_dbapiunicode_nocextensions 455858 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_oracle_cx_oracle_dbapiunicode_cextensions 455708 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 455708 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_postgresql_psycopg2_dbapiunicode_cextensions 476346 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 476346 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_cextensions 476346 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 476346 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_postgresql_psycopg2_dbapiunicode_cextensions 449362 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 449357 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_cextensions 449357 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 449362 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_postgresql_psycopg2_dbapiunicode_cextensions 488504 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 488504 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_cextensions 488504 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 488504 # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_mssql_pyodbc_dbapiunicode_cextensions 466544 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_mssql_pyodbc_dbapiunicode_nocextensions 479246 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_mysql_mysqldb_dbapiunicode_cextensions 448590 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_mysql_mysqldb_dbapiunicode_nocextensions 461390 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_oracle_cx_oracle_dbapiunicode_cextensions 553130 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 565832 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_postgresql_psycopg2_dbapiunicode_cextensions 448488 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 461288 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 444802 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 457602 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_mysql_mysqldb_dbapiunicode_cextensions 453303 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_mysql_mysqldb_dbapiunicode_nocextensions 466303 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_oracle_cx_oracle_dbapiunicode_cextensions 557941 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 570941 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_postgresql_psycopg2_dbapiunicode_cextensions 469901 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 482999 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 451115 -test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 464213 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_postgresql_psycopg2_dbapiunicode_cextensions 447788 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 460588 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 444102 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 456902 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_postgresql_psycopg2_dbapiunicode_cextensions 469298 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 482298 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 450512 +test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 463512 # TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mssql_pyodbc_dbapiunicode_cextensions 21984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mssql_pyodbc_dbapiunicode_nocextensions 21984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mysql_mysqldb_dbapiunicode_cextensions 21984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_mysql_mysqldb_dbapiunicode_nocextensions 21984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_oracle_cx_oracle_dbapiunicode_cextensions 21984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 21984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_dbapiunicode_cextensions 21984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 21984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_dbapiunicode_cextensions 21984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 21984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_mysql_mysqldb_dbapiunicode_cextensions 22984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_mysql_mysqldb_dbapiunicode_nocextensions 22984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_oracle_cx_oracle_dbapiunicode_cextensions 22984 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 22984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_postgresql_psycopg2_dbapiunicode_cextensions 22984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 22984 test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity 3.7_sqlite_pysqlite_dbapiunicode_cextensions 22984 @@ -487,45 +463,25 @@ 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_mssql_pyodbc_dbapiunicode_cextensions 89778 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mssql_pyodbc_dbapiunicode_nocextensions 91530 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_dbapiunicode_cextensions 99964 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_mysql_mysqldb_dbapiunicode_nocextensions 101765 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_oracle_cx_oracle_dbapiunicode_cextensions 97720 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 99521 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_dbapiunicode_cextensions 91217 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 92969 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_cextensions 89968 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 91771 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_mysql_mysqldb_dbapiunicode_cextensions 102537 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_mysql_mysqldb_dbapiunicode_nocextensions 104291 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_oracle_cx_oracle_dbapiunicode_cextensions 99793 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 101547 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_postgresql_psycopg2_dbapiunicode_cextensions 94292 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 96046 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_cextensions 92043 -test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 93797 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_dbapiunicode_cextensions 91469 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 93221 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_cextensions 90220 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 91972 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_postgresql_psycopg2_dbapiunicode_cextensions 94544 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 96298 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_cextensions 92295 +test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 94049 # 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_mssql_pyodbc_dbapiunicode_cextensions 18454 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mssql_pyodbc_dbapiunicode_nocextensions 18630 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_dbapiunicode_cextensions 18768 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_mysql_mysqldb_dbapiunicode_nocextensions 18992 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_oracle_cx_oracle_dbapiunicode_cextensions 19043 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 19316 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_dbapiunicode_cextensions 18343 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 18567 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_cextensions 18206 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 18430 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_mysql_mysqldb_dbapiunicode_cextensions 19415 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_mysql_mysqldb_dbapiunicode_nocextensions 19659 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_oracle_cx_oracle_dbapiunicode_cextensions 19707 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 19939 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_postgresql_psycopg2_dbapiunicode_cextensions 19014 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 19258 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_cextensions 18880 -test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 19124 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_dbapiunicode_cextensions 18297 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 18521 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_cextensions 18262 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 18486 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_postgresql_psycopg2_dbapiunicode_cextensions 19019 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 19263 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_cextensions 18885 +test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 19129 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load @@ -535,18 +491,18 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_dbapiuni test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_mysql_mysqldb_dbapiunicode_nocextensions 1213 test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_oracle_cx_oracle_dbapiunicode_cextensions 1111 test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 1128 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_dbapiunicode_cextensions 1142 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 1159 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_cextensions 998 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1015 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_dbapiunicode_cextensions 1143 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 1160 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_cextensions 999 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1016 test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_mysql_mysqldb_dbapiunicode_cextensions 1242 test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_mysql_mysqldb_dbapiunicode_nocextensions 1261 test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_oracle_cx_oracle_dbapiunicode_cextensions 1138 test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 1157 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_postgresql_psycopg2_dbapiunicode_cextensions 1162 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 1181 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1033 -test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1052 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_postgresql_psycopg2_dbapiunicode_cextensions 1163 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 1182 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1034 +test.aaa_profiling.test_orm.MergeTest.test_merge_load 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1053 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load @@ -577,18 +533,18 @@ test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_mysql_mysqldb_dbapiuni test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_mysql_mysqldb_dbapiunicode_nocextensions 6840 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_oracle_cx_oracle_dbapiunicode_cextensions 6360 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 8190 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6108 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6658 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 6052 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6602 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6100 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6650 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 6044 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6594 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_mysql_mysqldb_dbapiunicode_cextensions 6483 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_mysql_mysqldb_dbapiunicode_nocextensions 7143 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_oracle_cx_oracle_dbapiunicode_cextensions 6473 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 7043 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_postgresql_psycopg2_dbapiunicode_cextensions 6391 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6961 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_cextensions 6253 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6823 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_postgresql_psycopg2_dbapiunicode_cextensions 6383 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6953 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_cextensions 6335 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6815 # TEST: test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results @@ -598,18 +554,18 @@ test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_my test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_mysql_mysqldb_dbapiunicode_nocextensions 182353 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_oracle_cx_oracle_dbapiunicode_cextensions 188198 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 192504 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_postgresql_psycopg2_dbapiunicode_cextensions 168839 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 173243 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 164747 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 169151 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_postgresql_psycopg2_dbapiunicode_cextensions 169005 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 173409 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_cextensions 164913 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 169317 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_mysql_mysqldb_dbapiunicode_cextensions 183039 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_mysql_mysqldb_dbapiunicode_nocextensions 187847 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_oracle_cx_oracle_dbapiunicode_cextensions 192818 test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 197426 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_postgresql_psycopg2_dbapiunicode_cextensions 175514 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 180222 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 170822 -test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 175530 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_postgresql_psycopg2_dbapiunicode_cextensions 175680 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 180388 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_cextensions 171188 +test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 175696 # TEST: test.aaa_profiling.test_orm.SessionTest.test_expire_lots @@ -619,18 +575,18 @@ test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_mysql_mysqldb_dbapi test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_mysql_mysqldb_dbapiunicode_nocextensions 1147 test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_oracle_cx_oracle_dbapiunicode_cextensions 1156 test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 1142 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_postgresql_psycopg2_dbapiunicode_cextensions 1143 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 1136 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1146 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1156 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_postgresql_psycopg2_dbapiunicode_cextensions 1154 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 1154 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_cextensions 1155 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 1139 test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_mysql_mysqldb_dbapiunicode_cextensions 1256 test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_mysql_mysqldb_dbapiunicode_nocextensions 1258 test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_oracle_cx_oracle_dbapiunicode_cextensions 1257 test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 1242 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_postgresql_psycopg2_dbapiunicode_cextensions 1276 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 1248 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1265 -test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1274 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_postgresql_psycopg2_dbapiunicode_cextensions 1258 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 1261 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_cextensions 1279 +test.aaa_profiling.test_orm.SessionTest.test_expire_lots 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 1250 # TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect @@ -830,20 +786,20 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_db test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 137498 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 45577 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 501 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15503 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 464 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15466 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 489 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15491 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 452 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15454 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_cextensions 530 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_nocextensions 14534 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 102292 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_oracle_cx_oracle_dbapiunicode_cextensions 537 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 14541 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_cextensions 524 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 14528 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_cextensions 482 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 14486 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_cextensions 511 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 14515 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_cextensions 469 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 14473 # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_unicode @@ -855,31 +811,31 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_d test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 137498 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 45577 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 501 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15503 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 464 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15466 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 489 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15491 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 452 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15454 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_cextensions 530 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_nocextensions 14534 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 102292 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_oracle_cx_oracle_dbapiunicode_cextensions 537 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_oracle_cx_oracle_dbapiunicode_nocextensions 14541 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_cextensions 524 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 14528 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_cextensions 482 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 14486 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_cextensions 511 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 14515 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_cextensions 469 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 14473 # TEST: test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6473,328,3985,12867,1217,2209,2667 -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6517,328,4105,14171,1332,2222,2898 -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 6189,308,3953,12802,1206,2147,2719 -test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6272,308,4081,14064,1317,2166,2927 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6472,328,3905,12599,1208,2183,2632 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6516,328,4025,13903,1323,2196,2863 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 6205,309,3865,12511,1193,2118,2684 +test.aaa_profiling.test_zoomark.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 6288,309,3993,13773,1304,2137,2892 # 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 7045,414,7183,18831,1234,2854 -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 7136,419,7303,19900,1340,2889 -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 7054,406,7379,19439,1224,2924 -test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 7143,411,7515,20550,1327,2966 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_cextensions 7056,415,7170,18831,1225,2853 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 7146,420,7290,19900,1331,2888 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_cextensions 7080,408,7366,19439,1211,2923 +test.aaa_profiling.test_zoomark_orm.ZooMarkTest.test_invocation 3.7_postgresql_psycopg2_dbapiunicode_nocextensions 7176,413,7502,20550,1314,2965 diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index ea1a9bd75..cd462fb77 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -531,8 +531,7 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): ) def test_dupe_columns(self): - """test that deduping is performed against clause - element identity, not rendered result.""" + """as of 1.4, there's no deduping.""" self.assert_compile( select([column("a"), column("a"), column("a")]), @@ -542,13 +541,15 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): c = column("a") self.assert_compile( - select([c, c, c]), "SELECT a", dialect=default.DefaultDialect() + select([c, c, c]), + "SELECT a, a, a", + dialect=default.DefaultDialect(), ) a, b = column("a"), column("b") self.assert_compile( select([a, b, b, b, a, a]), - "SELECT a, b", + "SELECT a, b, b, b, a, a", dialect=default.DefaultDialect(), ) @@ -560,7 +561,7 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): ) self.assert_compile( select([a, b, c, a, b, c]), - "SELECT a, b, c", + "SELECT a, b, c, a, b, c", dialect=default.DefaultDialect(), ) @@ -584,6 +585,18 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): s = s.compile(dialect=default.DefaultDialect(paramstyle="qmark")) eq_(s.positiontup, ["a", "b", "c"]) + def test_dupe_columns_use_labels(self): + """as of 1.4, there's no deduping. + + however the labels will still uniqify themselves... + """ + + t = table("t", column("a"), column("b")) + self.assert_compile( + select([t.c.a, t.c.a, t.c.b]).apply_labels(), + "SELECT t.a AS t_a, t.a AS t_a_1, t.b AS t_b FROM t", + ) + def test_nested_label_targeting(self): """test nested anonymous label generation. @@ -2050,6 +2063,22 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): {"param_1": 10}, ) + def test_dupe_cols_hey_we_can_union(self): + """test the original inspiration for [ticket:4753].""" + + s1 = select([table1, table1.c.myid]).where(table1.c.myid == 5) + s2 = select([table1, table2.c.otherid]).where( + table1.c.myid == table2.c.otherid + ) + self.assert_compile( + union(s1, s2).order_by(s1.selected_columns.myid), + "SELECT mytable.myid, mytable.name, mytable.description, " + "mytable.myid FROM mytable WHERE mytable.myid = :myid_1 " + "UNION SELECT mytable.myid, mytable.name, mytable.description, " + "myothertable.otherid FROM mytable, myothertable " + "WHERE mytable.myid = myothertable.otherid ORDER BY myid", + ) + def test_compound_grouping(self): s = select([column("foo"), column("bar")]).select_from(text("bat")) @@ -4511,7 +4540,8 @@ class ResultMapTest(fixtures.TestBase): t = table("a", column("x"), column("y"), column("z")) l1, l2, l3 = t.c.z.label("a"), t.c.x.label("b"), t.c.x.label("c") - orig = [t.c.x, t.c.y, l1, l2, l3] + + orig = [t.c.x, t.c.y, l1, t.c.y, l2, t.c.x, l3] # create the statement with some duplicate columns. right now # the behavior is that these redundant columns are deduped. @@ -4520,11 +4550,11 @@ class ResultMapTest(fixtures.TestBase): # so the statement has 7 inner columns... eq_(len(list(stmt.inner_columns)), 7) - # but only exposes 5 of them, the other two are dupes of x and y - eq_(len(stmt.subquery().c), 5) + # 7 are exposed as of 1.4, no more deduping + eq_(len(stmt.subquery().c), 7) - # and when it generates a SELECT it will also render only 5 - eq_(len(stmt._columns_plus_names), 5) + # will render 7 as well + eq_(len(stmt._columns_plus_names), 7) wrapped = stmt._generate() wrapped = wrapped.column( @@ -4543,4 +4573,5 @@ class ResultMapTest(fixtures.TestBase): proxied = [obj[0] for (k, n, obj, type_) in compiled._result_columns] for orig_obj, proxied_obj in zip(orig, proxied): + is_(orig_obj, proxied_obj) diff --git a/test/sql/test_cte.py b/test/sql/test_cte.py index ac46e7d5d..26f367e9f 100644 --- a/test/sql/test_cte.py +++ b/test/sql/test_cte.py @@ -815,6 +815,7 @@ class CTETest(fixtures.TestBase, AssertsCompiledSQL): "regional_sales_1 " "AS anon_2, regional_sales_1 " 'WHERE orders."order" = :3) SELECT regional_sales_2.anon_1, ' + 'regional_sales_2."order", regional_sales_2."order", ' 'regional_sales_2."order" FROM regional_sales_2', checkpositional=("x", "y", "z"), dialect=dialect, @@ -862,8 +863,9 @@ class CTETest(fixtures.TestBase, AssertsCompiledSQL): 'regional_sales_1."order" AS "order" ' "FROM orders, regional_sales_1 AS anon_2, regional_sales_1 " "WHERE orders.\"order\" = 'z') " - 'SELECT regional_sales_2.anon_1, regional_sales_2."order" ' - "FROM regional_sales_2", + "SELECT regional_sales_2.anon_1, " + 'regional_sales_2."order", regional_sales_2."order", ' + 'regional_sales_2."order" FROM regional_sales_2', checkpositional=(), dialect=dialect, literal_binds=True, diff --git a/test/sql/test_join_rewriting.py b/test/sql/test_join_rewriting.py index a966af4e4..573455e7d 100644 --- a/test/sql/test_join_rewriting.py +++ b/test/sql/test_join_rewriting.py @@ -7,6 +7,7 @@ from sqlalchemy import Column from sqlalchemy import exists from sqlalchemy import ForeignKey from sqlalchemy import Integer +from sqlalchemy import literal_column from sqlalchemy import MetaData from sqlalchemy import select from sqlalchemy import Table @@ -14,10 +15,11 @@ from sqlalchemy import testing from sqlalchemy import union from sqlalchemy import util from sqlalchemy.engine import default +from sqlalchemy.sql import elements from sqlalchemy.testing import AssertsCompiledSQL +from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures - m = MetaData() @@ -92,11 +94,15 @@ class _JoinRewriteTestBase(AssertsCompiledSQL): compiled = s.compile(dialect=self.__dialect__) - # column name should be in result map, as we never render - # .key in SQL - for key, col in zip([c.name for c in s.subquery().c], s.inner_columns): - key = key % compiled.anon_map - assert col in compiled._create_result_map()[key][1] + for rec, (name, col) in zip( + compiled._result_columns, s._columns_plus_names + ): + assert col in set(rec[2]) + if ( + not isinstance(name, elements._anonymous_label) + and name is not None + ): + eq_(rec[1], name) _a_bkeyselect_bkey = "" @@ -128,6 +134,48 @@ class _JoinRewriteTestBase(AssertsCompiledSQL): self._test(s, self._a_bc) + def test_a_bc_preserve_dupes(self): + j1 = b.join(c) + j2 = a.join(j1) + + s = ( + select( + [a.c.id, b.c.id, b.c.a_id, c, b.c.a_id, c.c.b_id], + use_labels=True, + ) + .select_from(j2) + .where(b.c.id == 2) + .where(c.c.id == 3) + .order_by(a.c.id, b.c.id, c.c.id) + ) + + self._test(s, self._a_bc_wdupes) + + def test_a_bc_preserve_dupes_anon_map(self): + j1 = b.join(c) + j2 = a.join(j1) + + s = ( + select( + [a.c.id, b.c.id, b.c.a_id, c, b.c.a_id, c.c.b_id], + use_labels=True, + ) + .select_from(j2) + .where(b.c.id == 2) + .where(c.c.id == 3) + ) + + # the anon_map needs to be preserved after the transform + # as the labels are going to be referred to outside of the query + subq = s.subquery() + s2 = ( + select([literal_column("1")]) + .select_from(subq) + .where(subq.c[5] == subq.c[6]) + ) + + self._test(s2, self._a_bc_wdupes_anon_map) + def test_a_bkeyassoc(self): j1 = b_key.join(a_to_b_key) j2 = a.join(j1) @@ -311,6 +359,35 @@ class JoinRewriteTest(_JoinRewriteTestBase, fixtures.TestBase): "ORDER BY a.id, anon_1.b_id, anon_1.c_id" ) + _a_bc_wdupes = ( + "SELECT a.id AS a_id, anon_1.b_id AS b_id, anon_1.b_a_id AS b_a_id, " + "anon_1.c_id AS c_id, anon_1.c_b_id AS c_b_id, " + "anon_1.b_a_id AS b_a_id_1, anon_1.c_b_id AS c_b_id_1 " + "FROM a JOIN " + "(SELECT b.id AS b_id, b.a_id AS b_a_id, c.id AS c_id, " + "c.b_id AS c_b_id " + "FROM b JOIN c ON b.id = c.b_id) AS anon_1 ON a.id = anon_1.b_a_id " + "WHERE anon_1.b_id = :id_1 AND anon_1.c_id = :id_2 " + "ORDER BY a.id, anon_1.b_id, anon_1.c_id" + ) + + _a_bc_wdupes_anon_map = ( + "SELECT 1 FROM (SELECT a.id AS a_id, b.id AS b_id, b.a_id AS b_a_id, " + "c.id AS c_id, c.b_id AS c_b_id, b.a_id AS b_a_id_1, " + "c.b_id AS c_b_id_1 " + "FROM a JOIN (b JOIN c ON b.id = c.b_id) ON a.id = b.a_id " + "WHERE b.id = :id_1 AND c.id = :id_2) AS anon_1 " + "WHERE anon_1.b_a_id_1 = anon_1.c_b_id_1" + ) + + _a_bc_wdupes_anon_map = ( + "SELECT 1 FROM (SELECT a.id AS a_id, b.id AS b_id, b.a_id AS b_a_id, " + "c.id AS c_id, c.b_id AS c_b_id, b.a_id AS b_a_id_1, " + "c.b_id AS c_b_id_1 FROM a JOIN (b JOIN c ON b.id = c.b_id) " + "ON a.id = b.a_id WHERE b.id = :id_1 AND c.id = :id_2) AS anon_1 " + "WHERE anon_1.b_a_id_1 = anon_1.c_b_id_1" + ) + _a_bc_comma_a1_selbc = ( "SELECT a.id AS a_id, a_1.id AS a_1_id, anon_1.b_id AS b_id, " "anon_1.b_a_id AS b_a_id, anon_1.c_id AS c_id, " @@ -346,15 +423,14 @@ class JoinRewriteTest(_JoinRewriteTestBase, fixtures.TestBase): ) _a_bkeyselect_bkey = ( - "SELECT a.id AS a_id, anon_2.anon_1_aid AS anon_1_aid, " - "anon_2.anon_1_bid AS anon_1_bid, anon_2.b_key_id AS b_key_id " - "FROM a JOIN (SELECT anon_1.aid AS anon_1_aid, " - "anon_1.bid AS anon_1_bid, " + "SELECT a.id AS a_id, anon_1.b_key_id AS b_key_id " + "FROM a JOIN (SELECT anon_2.aid AS anon_2_aid, " + "anon_2.bid AS anon_2_bid, " "b_key.id AS b_key_id " "FROM (SELECT a_to_b_key.aid AS aid, a_to_b_key.bid AS bid " - "FROM a_to_b_key) AS anon_1 " - "JOIN b_key ON b_key.id = anon_1.bid) AS anon_2 " - "ON a.id = anon_2.anon_1_aid" + "FROM a_to_b_key) AS anon_2 " + "JOIN b_key ON b_key.id = anon_2.bid) AS anon_1 " + "ON a.id = anon_1.anon_2_aid" ) _a_atobalias_balias_c_w_exists = ( @@ -400,8 +476,8 @@ class JoinRewriteTest(_JoinRewriteTestBase, fixtures.TestBase): _b_a_id_double_overlap_annotated = ( "SELECT anon_1.b_id AS anon_1_b_id, anon_1.b_a_id AS anon_1_b_a_id, " - "anon_1.id_1 AS anon_1_id_1 " - "FROM (SELECT b.id AS b_id, b.a_id AS b_a_id, b_a.id AS id_1 " + "anon_1.b_a_id_1 AS anon_1_b_a_id_1 " + "FROM (SELECT b.id AS b_id, b.a_id AS b_a_id, b_a.id AS b_a_id_2 " "FROM b JOIN b_a ON b.id = b_a.id) AS anon_1" ) @@ -433,6 +509,7 @@ class JoinPlainTest(_JoinRewriteTestBase, fixtures.TestBase): "FROM a_to_b_key) AS anon_1 JOIN b_key ON b_key.id = anon_1.bid) " "ON a.id = anon_1.aid" ) + _a__b_dc = ( "SELECT a.id AS a_id, b.id AS b_id, " "b.a_id AS b_a_id, c.id AS c_id, " @@ -455,6 +532,25 @@ class JoinPlainTest(_JoinRewriteTestBase, fixtures.TestBase): "ORDER BY a.id, b.id, c.id" ) + _a_bc_wdupes = ( + "SELECT a.id AS a_id, b.id AS b_id, b.a_id AS b_a_id, c.id AS c_id, " + "c.b_id AS c_b_id, b.a_id AS b_a_id_1, c.b_id AS c_b_id_1 " + "FROM a JOIN " + "(b JOIN c ON b.id = c.b_id) " + "ON a.id = b.a_id " + "WHERE b.id = :id_1 AND c.id = :id_2 " + "ORDER BY a.id, b.id, c.id" + ) + + _a_bc_wdupes_anon_map = ( + "SELECT 1 FROM (SELECT a.id AS a_id, b.id AS b_id, b.a_id AS b_a_id, " + "c.id AS c_id, c.b_id AS c_b_id, b.a_id AS b_a_id_1, " + "c.b_id AS c_b_id_1 " + "FROM a JOIN (b JOIN c ON b.id = c.b_id) ON a.id = b.a_id " + "WHERE b.id = :id_1 AND c.id = :id_2) AS anon_1 " + "WHERE anon_1.b_a_id_1 = anon_1.c_b_id_1" + ) + _a_bc_comma_a1_selbc = ( "SELECT a.id AS a_id, a_1.id AS a_1_id, b.id AS b_id, " "b.a_id AS b_a_id, c.id AS c_id, " @@ -517,8 +613,8 @@ class JoinPlainTest(_JoinRewriteTestBase, fixtures.TestBase): _b_a_id_double_overlap_annotated = ( "SELECT anon_1.b_id AS anon_1_b_id, anon_1.b_a_id AS anon_1_b_a_id, " - "anon_1.id_1 AS anon_1_id_1 FROM " - "(SELECT b.id AS b_id, b.a_id AS b_a_id, b_a.id AS id_1 " + "anon_1.b_a_id_1 AS anon_1_b_a_id_1 FROM " + "(SELECT b.id AS b_id, b.a_id AS b_a_id, b_a.id AS b_a_id_1 " "FROM b JOIN b_a ON b.id = b_a.id) AS anon_1" ) @@ -573,6 +669,24 @@ class JoinNoUseLabelsTest(_JoinRewriteTestBase, fixtures.TestBase): "ORDER BY a.id, b.id, c.id" ) + _a_bc_wdupes = ( + "SELECT a.id, b.id, b.a_id, c.id, c.b_id, b.a_id, c.b_id " + "FROM a JOIN " + "(b JOIN c ON b.id = c.b_id) " + "ON a.id = b.a_id " + "WHERE b.id = :id_1 AND c.id = :id_2 " + "ORDER BY a.id, b.id, c.id" + ) + + _a_bc_wdupes_anon_map = ( + "SELECT 1 FROM (SELECT a.id AS a_id, b.id AS b_id, b.a_id AS b_a_id, " + "c.id AS c_id, c.b_id AS c_b_id, b.a_id AS b_a_id_1, " + "c.b_id AS c_b_id_1 " + "FROM a JOIN (b JOIN c ON b.id = c.b_id) ON a.id = b.a_id " + "WHERE b.id = :id_1 AND c.id = :id_2) AS anon_1 " + "WHERE anon_1.b_a_id_1 = anon_1.c_b_id_1" + ) + _a_bc_comma_a1_selbc = ( "SELECT a.id, a_1.id, b.id, " "b.a_id, c.id, " @@ -626,8 +740,8 @@ class JoinNoUseLabelsTest(_JoinRewriteTestBase, fixtures.TestBase): ) _b_a_id_double_overlap_annotated = ( - "SELECT anon_1.b_id, anon_1.b_a_id, anon_1.id_1 FROM " - "(SELECT b.id AS b_id, b.a_id AS b_a_id, b_a.id AS id_1 " + "SELECT anon_1.b_id, anon_1.b_a_id, anon_1.b_a_id_1 FROM " + "(SELECT b.id AS b_id, b.a_id AS b_a_id, b_a.id AS b_a_id_1 " "FROM b JOIN b_a ON b.id = b_a.id) AS anon_1" ) @@ -650,6 +764,10 @@ class JoinExecTest(_JoinRewriteTestBase, fixtures.TestBase): __backend__ = True _a_bc = ( + _a_bc_wdupes + ) = ( + _a_bc_wdupes_anon_map + ) = ( _a_bc_comma_a1_selbc ) = ( _a__b_dc diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 5081cfbd2..f3fa008c5 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -1518,6 +1518,7 @@ class TableTest(fixtures.TestBase, AssertsCompiledSQL): y = Column("y", Integer) t1 = Table("t", m, Column("x", Integer), y) + # note we are testing immutable column collection here t2 = pickle.loads(pickle.dumps(t1)) z = Column("z", Integer) g = Column("g", Integer) @@ -2530,7 +2531,7 @@ class ConstraintTest(fixtures.TestBase): i = Index("i", t.c.x, _table=t) is_(i.table, t) - eq_(i.columns, [t.c.x]) + eq_(list(i.columns), [t.c.x]) def test_inline_decl_columns(self): m = MetaData() diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index 485a0e428..9bcdd0620 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -656,27 +656,23 @@ class SelectableTest( s2 = select([table2.c.col1, table2.c.col2, table2.c.col3]) u1 = union(s1, s2).subquery() - with testing.expect_warnings("Column 'col1'"): - u1.c - assert ( u1.corresponding_column(s1.selected_columns._all_columns[0]) is u1.c._all_columns[0] ) - # due to the duplicate key, "col1" is now the column at the end - # of the list and the first column is not accessible by key - assert u1.c.col1 is u1.c._all_columns[2] + # col1 is taken by the first "col1" in the list + assert u1.c.col1 is u1.c._all_columns[0] # table2.c.col1 is in two positions in this union, so...currently # it is the replaced one at position 2. assert u1.corresponding_column(table2.c.col1) is u1.c._all_columns[2] - # this is table2.c.col1 in both cases, so this is "right" - assert u1.corresponding_column(s2.selected_columns.col1) is u1.c.col1 + # this is table2.c.col1, which in the first selectable is in position 2 + assert u1.corresponding_column(s2.selected_columns.col1) is u1.c[2] # same - assert u1.corresponding_column(s2.subquery().c.col1) is u1.c.col1 + assert u1.corresponding_column(s2.subquery().c.col1) is u1.c[2] # col2 is working OK assert u1.corresponding_column(s1.selected_columns.col2) is u1.c.col2 @@ -691,8 +687,8 @@ class SelectableTest( ) assert u1.corresponding_column(s2.subquery().c.col2) is u1.c.col2 - # col3 is also "correct" , though confusing - assert u1.corresponding_column(s2.selected_columns.col3) is u1.c.col1 + # col3 is also "correct" + assert u1.corresponding_column(s2.selected_columns.col3) is u1.c[2] assert u1.corresponding_column(table1.c.col1) is u1.c._all_columns[0] assert u1.corresponding_column(table1.c.col2) is u1.c._all_columns[1] @@ -705,22 +701,23 @@ class SelectableTest( s2 = select([table2.c.col1, table2.c.col2, table2.c.col3]).limit(1) u1 = union(s1, s2).subquery() - with testing.expect_warnings("Column 'col1'"): - u1.c + assert ( + u1.corresponding_column(s1.selected_columns._all_columns[0]) + is u1.c._all_columns[0] + ) - # due to the duplicate key, "col1" is now the column at the end - # of the list and the first column is not accessible by key - assert u1.c.col1 is u1.c._all_columns[2] + # col1 is taken by the first "col1" in the list + assert u1.c.col1 is u1.c._all_columns[0] # table2.c.col1 is in two positions in this union, so...currently # it is the replaced one at position 2. assert u1.corresponding_column(table2.c.col1) is u1.c._all_columns[2] - # this is table2.c.col1 in both cases, so this is "right" - assert u1.corresponding_column(s2.selected_columns.col1) is u1.c.col1 + # this is table2.c.col1, which in the first selectable is in position 2 + assert u1.corresponding_column(s2.selected_columns.col1) is u1.c[2] # same - assert u1.corresponding_column(s2.subquery().c.col1) is u1.c.col1 + assert u1.corresponding_column(s2.subquery().c.col1) is u1.c[2] # col2 is working OK assert u1.corresponding_column(s1.selected_columns.col2) is u1.c.col2 @@ -735,8 +732,8 @@ class SelectableTest( ) assert u1.corresponding_column(s2.subquery().c.col2) is u1.c.col2 - # col3 is also "correct" , though confusing - assert u1.corresponding_column(s2.selected_columns.col3) is u1.c.col1 + # col3 is also "correct" + assert u1.corresponding_column(s2.selected_columns.col3) is u1.c[2] assert u1.corresponding_column(table1.c.col1) is u1.c._all_columns[0] assert u1.corresponding_column(table1.c.col2) is u1.c._all_columns[1] @@ -2610,13 +2607,6 @@ class ReprTest(fixtures.TestBase): class WithLabelsTest(fixtures.TestBase): - def _assert_labels_warning(self, s): - assert_raises_message( - exc.SAWarning, - r"replaced by Column.*, which has the same key", - lambda: s.subquery().c, - ) - def _assert_result_keys(self, s, keys): compiled = s.compile() eq_(set(compiled._create_result_map()), set(keys)) @@ -2633,7 +2623,6 @@ class WithLabelsTest(fixtures.TestBase): def test_names_overlap_nolabel(self): sel = self._names_overlap() - self._assert_labels_warning(sel) self._assert_result_keys(sel, ["x"]) def test_names_overlap_label(self): @@ -2675,10 +2664,16 @@ class WithLabelsTest(fixtures.TestBase): def test_labels_overlap_label(self): sel = self._labels_overlap().apply_labels() t2 = sel.froms[1] - eq_(list(sel.selected_columns.keys()), ["t_x_id", t2.c.id.anon_label]) - eq_(list(sel.subquery().c.keys()), ["t_x_id", t2.c.id.anon_label]) - self._assert_result_keys(sel, ["t_x_id", "id_1"]) - self._assert_subq_result_keys(sel, ["t_x_id", "id_1"]) + eq_( + list(sel.selected_columns.keys()), + ["t_x_id", t2.c.id._label_anon_label], + ) + eq_( + list(sel.subquery().c.keys()), + ["t_x_id", t2.c.id._label_anon_label], + ) + self._assert_result_keys(sel, ["t_x_id", "t_x_id_1"]) + self._assert_subq_result_keys(sel, ["t_x_id", "t_x_id_1"]) def _labels_overlap_keylabels_dont(self): m = MetaData() @@ -2696,7 +2691,7 @@ class WithLabelsTest(fixtures.TestBase): sel = self._labels_overlap_keylabels_dont().apply_labels() eq_(list(sel.selected_columns.keys()), ["t_a", "t_x_b"]) eq_(list(sel.subquery().c.keys()), ["t_a", "t_x_b"]) - self._assert_result_keys(sel, ["t_x_id", "id_1"]) + self._assert_result_keys(sel, ["t_x_id", "t_x_id_1"]) def _keylabels_overlap_labels_dont(self): m = MetaData() @@ -2713,8 +2708,14 @@ class WithLabelsTest(fixtures.TestBase): def test_keylabels_overlap_labels_dont_label(self): sel = self._keylabels_overlap_labels_dont().apply_labels() t2 = sel.froms[1] - eq_(list(sel.selected_columns.keys()), ["t_x_id", t2.c.id.anon_label]) - eq_(list(sel.subquery().c.keys()), ["t_x_id", t2.c.id.anon_label]) + eq_( + list(sel.selected_columns.keys()), + ["t_x_id", t2.c.id._label_anon_label], + ) + eq_( + list(sel.subquery().c.keys()), + ["t_x_id", t2.c.id._label_anon_label], + ) self._assert_result_keys(sel, ["t_a", "t_x_b"]) self._assert_subq_result_keys(sel, ["t_a", "t_x_b"]) @@ -2734,10 +2735,13 @@ class WithLabelsTest(fixtures.TestBase): def test_keylabels_overlap_labels_overlap_label(self): sel = self._keylabels_overlap_labels_overlap().apply_labels() t2 = sel.froms[1] - eq_(list(sel.selected_columns.keys()), ["t_x_a", t2.c.a.anon_label]) - eq_(list(sel.subquery().c.keys()), ["t_x_a", t2.c.a.anon_label]) - self._assert_result_keys(sel, ["t_x_id", "id_1"]) - self._assert_subq_result_keys(sel, ["t_x_id", "id_1"]) + eq_( + list(sel.selected_columns.keys()), + ["t_x_a", t2.c.a._label_anon_label], + ) + eq_(list(sel.subquery().c.keys()), ["t_x_a", t2.c.a._label_anon_label]) + self._assert_result_keys(sel, ["t_x_id", "t_x_id_1"]) + self._assert_subq_result_keys(sel, ["t_x_id", "t_x_id_1"]) def _keys_overlap_names_dont(self): m = MetaData() @@ -2747,7 +2751,6 @@ class WithLabelsTest(fixtures.TestBase): def test_keys_overlap_names_dont_nolabel(self): sel = self._keys_overlap_names_dont() - self._assert_labels_warning(sel) self._assert_result_keys(sel, ["a", "b"]) def test_keys_overlap_names_dont_label(self): |