diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-04-23 11:50:47 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-04-23 11:50:47 -0400 |
| commit | 8f35f7a803c67f4ab0620686592a021a24e4b331 (patch) | |
| tree | c8245ecc0367a6ca6ab4bd7dfa68a99a2b952d9b | |
| parent | ff0fb31bf205a82c4af8781ac9afc96586a67d66 (diff) | |
| parent | 8b16cd876cb157d6f06863f2e345ff3e1d56972f (diff) | |
| download | sqlalchemy-8f35f7a803c67f4ab0620686592a021a24e4b331.tar.gz | |
- re-merge + CHANGES
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | CHANGES | 9 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 2 | ||||
| -rw-r--r-- | test/orm/test_froms.py | 82 |
5 files changed, 91 insertions, 5 deletions
@@ -5,6 +5,7 @@ Major contributing authors include: - Michael Bayer <mike_mp@zzzcomputing.com> - Jason Kirtland <jek@discorporate.us> - Gaetan de Menten <gdementen@gmail.com> +- Diana Clarke <diana.joan.clarke@gmail.com> - Michael Trier <mtrier@gmail.com> - Philip Jenvey <pjenvey@underboss.org> - Ants Aasma <ants.aasma@gmail.com> @@ -29,6 +29,15 @@ those which apply to an 0.7 release are noted. approach can be upgraded to this new approach. [ticket:1401] + - [feature] Query now "auto correlates" by + default in the same way as select() does. + Previously, a Query used as a subquery + in another would require the correlate() + method be called explicitly in order to + correlate a table on the inside to the + outside. As always, correlate(None) + disables correlation. [ticket:2179] + - [feature] Added prefix_with() method to Query, calls upon select().prefix_with() to allow placement of MySQL SELECT diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 924679085..b0ce9ee13 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -2907,7 +2907,6 @@ class Query(object): context.whereclause, from_obj=froms, use_labels=labels, - correlate=False, # TODO: this order_by is only needed if # LIMIT/OFFSET is present in self._select_args, # else the application on the outside is enough @@ -2973,7 +2972,6 @@ class Query(object): from_obj=froms, use_labels=labels, for_update=for_update, - correlate=False, order_by=context.order_by, **self._select_args ) diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 703fc0160..06b630076 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -749,7 +749,7 @@ class SubqueryLoader(AbstractRelationshipLoader): ): # reformat the original query # to look only for significant columns - q = orig_query._clone() + q = orig_query._clone().correlate(None) # TODO: why does polymporphic etc. require hardcoding # into _adapt_col_list ? Does query.add_columns(...) work diff --git a/test/orm/test_froms.py b/test/orm/test_froms.py index c8fc0af79..c41120bb9 100644 --- a/test/orm/test_froms.py +++ b/test/orm/test_froms.py @@ -66,6 +66,85 @@ class QueryTest(_fixtures.FixtureTest): configure_mappers() +class QueryCorrelatesLikeSelect(QueryTest, AssertsCompiledSQL): + + query_correlated = "SELECT users.name AS users_name, " \ + "(SELECT count(addresses.id) AS count_1 FROM addresses " \ + "WHERE addresses.user_id = users.id) AS anon_1 FROM users" + + query_not_correlated = "SELECT users.name AS users_name, " \ + "(SELECT count(addresses.id) AS count_1 FROM addresses, users " \ + "WHERE addresses.user_id = users.id) AS anon_1 FROM users" + + def test_as_scalar_select_auto_correlate(self): + addresses, users = self.tables.addresses, self.tables.users + query = select( + [func.count(addresses.c.id)], + addresses.c.user_id==users.c.id + ).as_scalar() + query = select([users.c.name.label('users_name'), query]) + self.assert_compile(query, self.query_correlated, + dialect=default.DefaultDialect() + ) + + def test_as_scalar_select_explicit_correlate(self): + addresses, users = self.tables.addresses, self.tables.users + query = select( + [func.count(addresses.c.id)], + addresses.c.user_id==users.c.id + ).correlate(users).as_scalar() + query = select([users.c.name.label('users_name'), query]) + self.assert_compile(query, self.query_correlated, + dialect=default.DefaultDialect() + ) + + def test_as_scalar_select_correlate_off(self): + addresses, users = self.tables.addresses, self.tables.users + query = select( + [func.count(addresses.c.id)], + addresses.c.user_id==users.c.id + ).correlate(None).as_scalar() + query = select([ users.c.name.label('users_name'), query]) + self.assert_compile(query, self.query_not_correlated, + dialect=default.DefaultDialect() + ) + + def test_as_scalar_query_auto_correlate(self): + sess = create_session() + Address, User = self.classes.Address, self.classes.User + query = sess.query(func.count(Address.id))\ + .filter(Address.user_id==User.id)\ + .as_scalar() + query = sess.query(User.name, query) + self.assert_compile(query, self.query_correlated, + dialect=default.DefaultDialect() + ) + + def test_as_scalar_query_explicit_correlate(self): + sess = create_session() + Address, User = self.classes.Address, self.classes.User + query = sess.query(func.count(Address.id))\ + .filter(Address.user_id==User.id)\ + .correlate(self.tables.users)\ + .as_scalar() + query = sess.query(User.name, query) + self.assert_compile(query, self.query_correlated, + dialect=default.DefaultDialect() + ) + + def test_as_scalar_query_correlate_off(self): + sess = create_session() + Address, User = self.classes.Address, self.classes.User + query = sess.query(func.count(Address.id))\ + .filter(Address.user_id==User.id)\ + .correlate(None)\ + .as_scalar() + query = sess.query(User.name, query) + self.assert_compile(query, self.query_not_correlated, + dialect=default.DefaultDialect() + ) + + class RawSelectTest(QueryTest, AssertsCompiledSQL): """compare a bunch of select() tests with the equivalent Query using straight table/columns. @@ -90,10 +169,9 @@ class RawSelectTest(QueryTest, AssertsCompiledSQL): ) # a little tedious here, adding labels to work around Query's auto-labelling. - # also correlate needed explicitly. hmmm..... # TODO: can we detect only one table in the "froms" and then turn off use_labels ? s = sess.query(addresses.c.id.label('id'), addresses.c.email_address.label('email')).\ - filter(addresses.c.user_id==users.c.id).correlate(users).statement.alias() + filter(addresses.c.user_id==users.c.id).statement.alias() self.assert_compile(sess.query(users, s.c.email).select_from(users.join(s, s.c.id==users.c.id)).with_labels().statement, "SELECT users.id AS users_id, users.name AS users_name, anon_1.email AS anon_1_email " |
