From: Mike Bayer Date: Wed, 20 Jan 2010 19:26:12 +0000 (+0000) Subject: - query.select_from() also accepts mapped classes, aliased() X-Git-Tag: rel_0_6beta1~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6973635136860a7ef6f5a5b4072d11163560fb3d;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - query.select_from() also accepts mapped classes, aliased() constructs, and mappers as arguments. In particular this helps when querying from multiple joined-table classes to ensure the full join gets rendered. --- diff --git a/CHANGES b/CHANGES index 2c1db03ccb..895344dc45 100644 --- a/CHANGES +++ b/CHANGES @@ -129,6 +129,11 @@ CHANGES multiple comma separated entries within the FROM clause. Useful when selecting from multiple-homed join() clauses. + - query.select_from() also accepts mapped classes, aliased() + constructs, and mappers as arguments. In particular this + helps when querying from multiple joined-table classes to ensure + the full join gets rendered. + - query.get() can be used with a mapping to an outer join where one or more of the primary key values are None. [ticket:1135] diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 0a7a738c8d..d288e20c15 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1167,14 +1167,24 @@ class Query(object): """Set the `from_obj` parameter of the query and return the newly resulting ``Query``. This replaces the table which this Query selects from with the given table. + + ``select_from()`` also accepts class arguments. Though usually not necessary, + can ensure that the full selectable of the given mapper is applied, e.g. + for joined-table mappers. """ + obj = [] for fo in from_obj: - if not isinstance(fo, expression.FromClause): + if _is_mapped_class(fo): + mapper, selectable, is_aliased_class = _entity_info(fo) + obj.append(selectable) + elif not isinstance(fo, expression.FromClause): raise sa_exc.ArgumentError("select_from() accepts FromClause objects only.") + else: + obj.append(fo) - self._set_select_from(*from_obj) + self._set_select_from(*obj) def __getitem__(self, item): if isinstance(item, slice): diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 22dd202093..c0835e74af 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -1302,6 +1302,33 @@ class InheritedJoinTest(_base.MappedTest, AssertsCompiledSQL): , use_default_dialect = True ) + @testing.resolve_artifact_names + def test_force_via_select_from(self): + sess = create_session() + + self.assert_compile( + sess.query(Company).\ + filter(Company.company_id==Engineer.company_id).\ + filter(Engineer.primary_language=='java'), + "SELECT companies.company_id AS companies_company_id, companies.name AS companies_name " + "FROM companies, people, engineers " + "WHERE companies.company_id = people.company_id AND engineers.primary_language " + "= :primary_language_1", + use_default_dialect=True + ) + + self.assert_compile( + sess.query(Company).select_from(Company, Engineer).\ + filter(Company.company_id==Engineer.company_id).\ + filter(Engineer.primary_language=='java'), + "SELECT companies.company_id AS companies_company_id, companies.name AS companies_name " + "FROM companies, people JOIN engineers ON people.person_id = engineers.person_id " + "WHERE companies.company_id = people.company_id AND engineers.primary_language =" + " :primary_language_1", + use_default_dialect=True + + ) + @testing.resolve_artifact_names def test_single_prop_of_type(self): sess = create_session()