summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-07-15 09:59:17 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-07-15 09:59:17 -0400
commit2bd3c795cfe39249aceb6b04ea4650a17788d9b6 (patch)
treec097a193f5632e6c9576af95fea198925ed450c4
parent10db67be5b783b94b59dd7cf039f8c322cf837c8 (diff)
downloadsqlalchemy-2bd3c795cfe39249aceb6b04ea4650a17788d9b6.tar.gz
- Column-entities (i.e. query(Foo.id)) copy theirrel_0_6_3
state more fully when queries are derived from themselves + a selectable (i.e. from_self(), union(), etc.), so that join() and such have the correct state to work from. [ticket:1853] - Fixed bug where Query.join() would fail if querying a non-ORM column then joining without an on clause when a FROM clause is already present, now raises a checked exception the same way it does when the clause is not present. [ticket:1853]
-rw-r--r--CHANGES13
-rw-r--r--lib/sqlalchemy/orm/query.py6
-rw-r--r--test/orm/test_query.py56
3 files changed, 73 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 09f69a069..12730f954 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,19 @@ CHANGES
and a delete of the parent has occurred.
[ticket:1845]
+ - Column-entities (i.e. query(Foo.id)) copy their
+ state more fully when queries are derived from
+ themselves + a selectable (i.e. from_self(),
+ union(), etc.), so that join() and such have the
+ correct state to work from. [ticket:1853]
+
+ - Fixed bug where Query.join() would fail if
+ querying a non-ORM column then joining without
+ an on clause when a FROM clause is already
+ present, now raises a checked exception the
+ same way it does when the clause is not
+ present. [ticket:1853]
+
- Improved the check for an "unmapped class",
including the case where the superclass is mapped
but the subclass is not. Any attempts to access
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 28ddc1f13..3f8300a09 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -1301,7 +1301,7 @@ class Query(object):
join_to_left = not is_aliased_class and not left_is_aliased
- if self._from_obj:
+ if self._from_obj and left_selectable is not None:
replace_clause_index, clause = sql_util.find_join_source(
self._from_obj,
left_selectable)
@@ -2622,7 +2622,9 @@ class _ColumnEntity(_QueryEntity):
return self.column.type
def adapt_to_selectable(self, query, sel):
- _ColumnEntity(query, sel.corresponding_column(self.column))
+ c = _ColumnEntity(query, sel.corresponding_column(self.column))
+ c.entity_zero = self.entity_zero
+ c.entities = self.entities
def setup_entity(self, entity, mapper, adapter, from_obj,
is_aliased_class, with_polymorphic):
diff --git a/test/orm/test_query.py b/test/orm/test_query.py
index ba8112db0..ebe72b565 100644
--- a/test/orm/test_query.py
+++ b/test/orm/test_query.py
@@ -2343,6 +2343,44 @@ class JoinTest(QueryTest, AssertsCompiledSQL):
(order3, item3),
]
)
+
+ def test_joins_from_adapted_entities(self):
+
+ # test for #1853
+
+ session = create_session()
+ first = session.query(User)
+ second = session.query(User)
+ unioned = first.union(second)
+ subquery = session.query(User.id).subquery()
+ join = subquery, subquery.c.id == User.id
+ joined = unioned.outerjoin(join)
+ self.assert_compile(joined,
+ 'SELECT anon_1.users_id AS '
+ 'anon_1_users_id, anon_1.users_name AS '
+ 'anon_1_users_name FROM (SELECT users.id '
+ 'AS users_id, users.name AS users_name '
+ 'FROM users UNION SELECT users.id AS '
+ 'users_id, users.name AS users_name FROM '
+ 'users) AS anon_1 LEFT OUTER JOIN (SELECT '
+ 'users.id AS id FROM users) AS anon_2 ON '
+ 'anon_2.id = anon_1.users_id',
+ use_default_dialect=True)
+
+ first = session.query(User.id)
+ second = session.query(User.id)
+ unioned = first.union(second)
+ subquery = session.query(User.id).subquery()
+ join = subquery, subquery.c.id == User.id
+ joined = unioned.outerjoin(join)
+ self.assert_compile(joined,
+ 'SELECT anon_1.users_id AS anon_1_users_id '
+ 'FROM (SELECT users.id AS users_id FROM '
+ 'users UNION SELECT users.id AS users_id '
+ 'FROM users) AS anon_1 LEFT OUTER JOIN '
+ '(SELECT users.id AS id FROM users) AS '
+ 'anon_2 ON anon_2.id = anon_1.users_id',
+ use_default_dialect=True)
def test_reset_joinpoint(self):
for aliased in (True, False):
@@ -2422,6 +2460,24 @@ class JoinTest(QueryTest, AssertsCompiledSQL):
sess.query(User.name).join((addresses, User.id==addresses.c.user_id)).order_by(User.id).all(),
[(u'jack',), (u'ed',), (u'ed',), (u'ed',), (u'fred',)]
)
+
+ def test_no_joinpoint_expr(self):
+ sess = create_session()
+
+ # these are consistent regardless of
+ # select_from() being present.
+
+ assert_raises_message(
+ sa_exc.InvalidRequestError,
+ "Could not find a FROM",
+ sess.query(users.c.id).join, User
+ )
+
+ assert_raises_message(
+ sa_exc.InvalidRequestError,
+ "Could not find a FROM",
+ sess.query(users.c.id).select_from(users).join, User
+ )
def test_from_self_resets_joinpaths(self):
"""test a join from from_self() doesn't confuse joins inside the subquery