summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-06-06 18:06:02 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2013-06-06 18:06:02 -0400
commit28c3325c4e18d01d7e0403229b452c8fbc345b80 (patch)
tree67576681ff561bcabeae0330bcf64c214bfe29aa /lib/sqlalchemy
parent768108186a48a94948a7763d0f5c4dfb3f0ce773 (diff)
downloadsqlalchemy-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.py2
-rw-r--r--lib/sqlalchemy/orm/query.py2
-rw-r--r--lib/sqlalchemy/orm/strategies.py12
-rw-r--r--lib/sqlalchemy/orm/util.py20
-rw-r--r--lib/sqlalchemy/sql/util.py11
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