From: Mike Bayer Date: Tue, 23 Mar 2010 22:53:42 +0000 (-0400) Subject: - added add_columns() to Query - pending deprecates add_column() X-Git-Tag: rel_0_6beta3~12^2~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ead3d6ab2fd323dad99c310cab7aa12d72f4f4ee;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - added add_columns() to Query - pending deprecates add_column() - refined subquery strategy to use more public Query API --- diff --git a/CHANGES b/CHANGES index 4640408e38..64bb290c2a 100644 --- a/CHANGES +++ b/CHANGES @@ -23,7 +23,11 @@ CHANGES load such as query(A).options(eagerload(A.b, B.c)) wouldn't eagerload anything, but using eagerload("b.c") would work fine. - + + - Query gains an add_columns(*columns) method which is a multi- + version of add_column(col). add_column(col) is future + deprecated. + 0.6beta2 ======== diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 2dfefc4332..5e7a2028e6 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -662,16 +662,25 @@ class Query(object): return None @_generative() - def add_column(self, column): - """Add a SQL ColumnElement to the list of result columns to be returned.""" + def add_columns(self, *column): + """Add one or more column expressions to the list + of result columns to be returned.""" self._entities = list(self._entities) l = len(self._entities) - _ColumnEntity(self, column) + for c in column: + _ColumnEntity(self, c) # _ColumnEntity may add many entities if the # given arg is a FROM clause self._setup_aliasizers(self._entities[l:]) + @util.pending_deprecation("add_column() superceded by add_columns()") + def add_column(self, column): + """Add a column expression to the list of result columns + to be returned.""" + + return self.add_columns(column) + def options(self, *args): """Return a new Query object, applying the given list of MapperOptions. diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 4431b408fc..b6ca1090d7 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -707,44 +707,38 @@ class SubqueryLoader(AbstractRelationshipLoader): q._attributes[('subquery_path', None)] = subq_path - # now select from it as a subquery. - local_attr = [ - self.parent._get_col_to_prop(c).class_attribute - for c in local_cols - ] - q = q.from_self(self.mapper) q._entities[0].disable_aliasing = True - to_join = [(subq_path[i], subq_path[i+1]) - for i in xrange(0, len(subq_path), 2)] - - for i, (mapper, key) in enumerate(to_join): - alias_join = i < len(to_join) - 1 - second_to_last = i == len(to_join) - 2 - - prop = mapper.get_property(key) - q = q.join(prop.class_attribute, aliased=alias_join) - - if alias_join and second_to_last: - cols = [ - q._adapt_clause(col, True, False) - for col in local_cols + to_join = [ + (subq_path[i], subq_path[i+1]) + for i in xrange(0, len(subq_path), 2) ] - for col in cols: - q = q.add_column(col) - q = q.order_by(*cols) - + if len(to_join) < 2: local_attr = [ self.parent._get_col_to_prop(c).class_attribute for c in local_cols ] - - for col in local_attr: - q = q.add_column(col) - q = q.order_by(*local_attr) - + else: + parent_alias = mapperutil.AliasedClass(self.parent) + local_attr = [ + getattr(parent_alias, self.parent._get_col_to_prop(c).key) + for c in local_cols + ] + q = q.add_columns(*local_attr) + q = q.order_by(*local_attr) + + for i, (mapper, key) in enumerate(to_join): + alias_join = i < len(to_join) - 1 + second_to_last = i == len(to_join) - 2 + + prop = mapper.get_property(key) + + if second_to_last: + q = q.join((parent_alias, prop.class_attribute)) + else: + q = q.join(prop.class_attribute, aliased=alias_join) # propagate loader options etc. to the new query q = q._with_current_path(subq_path) diff --git a/test/orm/inheritance/test_query.py b/test/orm/inheritance/test_query.py index 83297e165d..f7eb5d5e40 100644 --- a/test/orm/inheritance/test_query.py +++ b/test/orm/inheritance/test_query.py @@ -195,7 +195,8 @@ def _produce_test(select_type): sess = create_session() # assert the JOINs dont over JOIN - assert sess.query(Person).with_polymorphic('*').options(eagerload(Engineer.machines)).limit(2).offset(1).with_labels().subquery().count().scalar() == 2 + assert sess.query(Person).with_polymorphic('*').options(eagerload(Engineer.machines)).\ + limit(2).offset(1).with_labels().subquery().count().scalar() == 2 def go(): eq_(sess.query(Person).with_polymorphic('*').options(eagerload(Engineer.machines))[1:3], all_employees[1:3])