From 51e1019f610f083ac4d8c850589cdf52cff044da Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 4 Jun 2013 16:21:25 -0400 Subject: [PATCH] here's the flat join thing. it just works. Changing the existing compiled SQL assertions might even be most of the tests we need (though dedicated sql tests would be needed anyway) --- lib/sqlalchemy/orm/strategies.py | 3 ++- lib/sqlalchemy/orm/util.py | 5 +++-- lib/sqlalchemy/sql/expression.py | 19 ++++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index cabfb35b96..baaf4cb929 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -1089,7 +1089,8 @@ class JoinedLoader(AbstractRelationshipLoader): to_adapt = with_poly_info.entity else: to_adapt = orm_util.AliasedClass(self.mapper, - use_mapper_path=True) + use_mapper_path=True, + flat=True) clauses = orm_util.ORMAdapter( to_adapt, equivalents=self.mapper._equivalent_columns, diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index bd8228f2c1..3da6e89e3f 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -493,6 +493,7 @@ class AliasedClass(object): """ def __init__(self, cls, alias=None, name=None, + flat=False, adapt_on_names=False, # TODO: None for default here? with_polymorphic_mappers=(), @@ -501,7 +502,7 @@ class AliasedClass(object): use_mapper_path=False): mapper = _class_to_mapper(cls) if alias is None: - alias = mapper._with_polymorphic_selectable.alias(name=name) + alias = mapper._with_polymorphic_selectable.alias(name=name, flat=flat) self._aliased_insp = AliasedInsp( self, mapper, @@ -837,7 +838,7 @@ def with_polymorphic(base, classes, selectable=False, _with_polymorphic_args(classes, selectable, innerjoin=innerjoin) if aliased: - selectable = selectable.alias() + selectable = selectable.alias(flat=True) return AliasedClass(base, selectable, with_polymorphic_mappers=mappers, diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index edab9e2901..633a3ddba7 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -795,7 +795,7 @@ def intersect_all(*selects, **kwargs): return CompoundSelect(CompoundSelect.INTERSECT_ALL, *selects, **kwargs) -def alias(selectable, name=None): +def alias(selectable, name=None, flat=False): """Return an :class:`.Alias` object. An :class:`.Alias` represents any :class:`.FromClause` @@ -2634,7 +2634,7 @@ class FromClause(Selectable): return Join(self, right, onclause, True) - def alias(self, name=None): + def alias(self, name=None, flat=False): """return an alias of this :class:`.FromClause`. This is shorthand for calling:: @@ -3971,7 +3971,7 @@ class Join(FromClause): def bind(self): return self.left.bind or self.right.bind - def alias(self, name=None): + def alias(self, name=None, flat=False): """return an alias of this :class:`.Join`. Used against a :class:`.Join` object, @@ -3999,7 +3999,16 @@ class Join(FromClause): aliases. """ - return self.select(use_labels=True, correlate=False).alias(name) + if flat: + assert name is None, "Can't send name argument with flat" + left_a, right_a = self.left.alias(), self.right.alias() + adapter = sqlutil.ClauseAdapter(left_a).\ + chain(sqlutil.ClauseAdapter(right_a)) + + return left_a.join(right_a, + adapter.traverse(self.onclause), isouter=self.isouter) + else: + return self.select(use_labels=True, correlate=False).alias(name) @property def _hide_froms(self): @@ -4129,7 +4138,7 @@ class CTE(Alias): self._restates = _restates super(CTE, self).__init__(selectable, name=name) - def alias(self, name=None): + def alias(self, name=None, flat=False): return CTE( self.original, name=name, -- 2.47.3