mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-30 20:44:45 -04:00
- 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]
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user