diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-06-06 18:06:02 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-06-06 18:06:02 -0400 |
| commit | 28c3325c4e18d01d7e0403229b452c8fbc345b80 (patch) | |
| tree | 67576681ff561bcabeae0330bcf64c214bfe29aa /lib/sqlalchemy | |
| parent | 768108186a48a94948a7763d0f5c4dfb3f0ce773 (diff) | |
| download | sqlalchemy-28c3325c4e18d01d7e0403229b452c8fbc345b80.tar.gz | |
dial back the default "flatness" a bit, it will be there for joinedload and query.join(), but if
you're dealing with aliased() or with_polymorphic() you need to say "flat=True". Just the one
flag though, "flat" implies "aliased".
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 12 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 20 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/util.py | 11 |
5 files changed, 28 insertions, 19 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 285d338de..7f14d83cb 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1767,7 +1767,7 @@ class Mapper(_InspectionAttr): while stack: item = stack.popleft() descendants.append(item) - stack.extend(item._inheriting_mappers) + stack.extend(sorted(item._inheriting_mappers, key=lambda m: m.class_.__name__)) return util.WeakSequence(descendants) def polymorphic_iterator(self): diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index d251f983f..54f5d7393 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1897,7 +1897,7 @@ class Query(object): ) if not need_adapter and (create_aliases or aliased_entity): - right = aliased(right) + right = aliased(right, flat=True) need_adapter = True # if an alias() of the right side was generated here, diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index cabfb35b9..6394003b3 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -1060,6 +1060,14 @@ class JoinedLoader(AbstractRelationshipLoader): column_collection=add_to_collection, allow_innerjoin=allow_innerjoin) + if with_poly_info is not None and \ + None in set(context.secondary_columns): + raise sa_exc.InvalidRequestError( + "Detected unaliased columns when generating joined " + "load. Make sure to use aliased=True or flat=True " + "when using joined loading with with_polymorphic()." + ) + def _get_user_defined_adapter(self, context, entity, path, adapter, user_defined_adapter): @@ -1089,6 +1097,7 @@ class JoinedLoader(AbstractRelationshipLoader): to_adapt = with_poly_info.entity else: to_adapt = orm_util.AliasedClass(self.mapper, + flat=True, use_mapper_path=True) clauses = orm_util.ORMAdapter( to_adapt, @@ -1415,8 +1424,7 @@ class LoadEagerFromAliasOption(PropertyOption): "path_with_polymorphic") adapter = orm_util.ORMAdapter( with_poly_info.entity, - equivalents=prop.mapper._equivalent_columns, - adapt_required=True) + equivalents=prop.mapper._equivalent_columns) else: adapter = query._polymorphic_adapters.get(prop.mapper, None) paths[-1].set(query._attributes, diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index c21e7eace..7ac3ac96a 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -223,8 +223,8 @@ class ORMAdapter(sql_util.ColumnAdapter): and the AliasedClass if any is referenced. """ - def __init__(self, entity, equivalents=None, - chain_to=None, adapt_required=False): + def __init__(self, entity, equivalents=None, adapt_required=False, + chain_to=None): info = inspection.inspect(entity) self.mapper = info.mapper @@ -493,7 +493,7 @@ class AliasedClass(object): """ def __init__(self, cls, alias=None, name=None, - flat=True, + flat=False, adapt_on_names=False, # TODO: None for default here? with_polymorphic_mappers=(), @@ -502,7 +502,8 @@ class AliasedClass(object): use_mapper_path=False): mapper = _class_to_mapper(cls) if alias is None: - alias = mapper._with_polymorphic_selectable.alias(name=name, flat=flat) + alias = mapper._with_polymorphic_selectable.alias( + name=name, flat=flat) self._aliased_insp = AliasedInsp( self, mapper, @@ -701,7 +702,7 @@ inspection._inspects(AliasedClass)(lambda target: target._aliased_insp) inspection._inspects(AliasedInsp)(lambda target: target) -def aliased(element, alias=None, name=None, adapt_on_names=False): +def aliased(element, alias=None, name=None, flat=False, adapt_on_names=False): """Produce an alias of the given element, usually an :class:`.AliasedClass` instance. @@ -775,13 +776,14 @@ def aliased(element, alias=None, name=None, adapt_on_names=False): raise sa_exc.ArgumentError( "adapt_on_names only applies to ORM elements" ) - return element.alias(name) + return element.alias(name, flat=flat) else: - return AliasedClass(element, alias=alias, + return AliasedClass(element, alias=alias, flat=flat, name=name, adapt_on_names=adapt_on_names) def with_polymorphic(base, classes, selectable=False, + flat=False, polymorphic_on=None, aliased=False, innerjoin=False, _use_mapper_path=False): """Produce an :class:`.AliasedClass` construct which specifies @@ -837,8 +839,8 @@ def with_polymorphic(base, classes, selectable=False, mappers, selectable = primary_mapper.\ _with_polymorphic_args(classes, selectable, innerjoin=innerjoin) - if aliased: - selectable = selectable.alias(flat=True) + if aliased or flat: + selectable = selectable.alias(flat=flat) return AliasedClass(base, selectable, with_polymorphic_mappers=mappers, diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 6f4d27e1b..4422705cd 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -905,12 +905,11 @@ class ColumnAdapter(ClauseAdapter): if isinstance(c, expression.Label): c = c.label(None) - # adapt_required indicates that if we got the same column - # back which we put in (i.e. it passed through), - # it's not correct. this is used by eagerloading which - # knows that all columns and expressions need to be adapted - # to a result row, and a "passthrough" is definitely targeting - # the wrong column. + # adapt_required used by eager loading to indicate that + # we don't trust a result row column that is not translated. + # this is to prevent a column from being interpreted as that + # of the child row in a self-referential scenario, see + # inheritance/test_basic.py->EagerTargetingTest.test_adapt_stringency if self.adapt_required and c is col: return None |
