summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES13
-rw-r--r--lib/sqlalchemy/orm/query.py15
-rw-r--r--lib/sqlalchemy/orm/strategies.py1
-rw-r--r--test/orm/inheritance/test_single.py76
4 files changed, 100 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index a39fac9f0..657695c7e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -47,7 +47,18 @@ CHANGES
- Placing passive_deletes=True on a many-to-one emits
a warning, since you probably intended to put it on
the one-to-many side.
-
+
+ - Fixed bug that would prevent "subqueryload" from
+ working correctly with single table inheritance
+ for a relationship from a subclass - the "where
+ type in (x, y, z)" only gets placed on the inside,
+ instead of repeatedly.
+
+ - When using from_self() with single table inheritance,
+ the "where type in (x, y, z)" is placed on the outside
+ of the query only, instead of repeatedly. May make
+ some more adjustments to this.
+
0.6.4
=====
- orm
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 6c5e8c81c..b22a10b55 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -98,6 +98,7 @@ class Query(object):
_attributes = util.frozendict()
_with_options = ()
_with_hints = ()
+ _enable_single_crit = True
def __init__(self, entities, session=None):
self.session = session
@@ -701,12 +702,17 @@ class Query(object):
"""
fromclause = self.with_labels().enable_eagerloads(False).\
+ _enable_single_crit(False).\
statement.correlate(None)
q = self._from_selectable(fromclause)
if entities:
q._set_entities(entities)
return q
-
+
+ @_generative()
+ def _enable_single_crit(self, val):
+ self._enable_single_crit = val
+
@_generative()
def _from_selectable(self, fromclause):
for attr in ('_statement', '_criterion', '_order_by', '_group_by',
@@ -1936,7 +1942,8 @@ class Query(object):
else:
from_obj = context.froms
- self._adjust_for_single_inheritance(context)
+ if self._enable_single_crit:
+ self._adjust_for_single_inheritance(context)
whereclause = context.whereclause
@@ -2273,7 +2280,8 @@ class Query(object):
# i.e. when each _MappedEntity has its own FROM
froms = context.froms
- self._adjust_for_single_inheritance(context)
+ if self._enable_single_crit:
+ self._adjust_for_single_inheritance(context)
if not context.primary_columns:
if self._only_load_props:
@@ -2405,6 +2413,7 @@ class Query(object):
selected from the total results.
"""
+
for entity, (mapper, adapter, s, i, w) in \
self._mapper_adapter_map.iteritems():
single_crit = mapper._single_table_criterion
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index b0a18b7dd..3e6b6a21f 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -765,6 +765,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
("orig_query", SubqueryLoader): orig_query,
('subquery_path', None) : subq_path
}
+ q = q._enable_single_crit(False)
# figure out what's being joined. a.k.a. the fun part
to_join = [
diff --git a/test/orm/inheritance/test_single.py b/test/orm/inheritance/test_single.py
index 4b7078eb5..420430954 100644
--- a/test/orm/inheritance/test_single.py
+++ b/test/orm/inheritance/test_single.py
@@ -8,7 +8,7 @@ from test.orm._base import MappedTest, ComparableEntity
from sqlalchemy.test.schema import Table, Column
-class SingleInheritanceTest(MappedTest):
+class SingleInheritanceTest(testing.AssertsCompiledSQL, MappedTest):
@classmethod
def define_tables(cls, metadata):
Table('employees', metadata,
@@ -26,6 +26,7 @@ class SingleInheritanceTest(MappedTest):
@classmethod
def setup_classes(cls):
+ global Employee, Manager, Engineer, JuniorEngineer
class Employee(ComparableEntity):
pass
class Manager(Employee):
@@ -114,6 +115,31 @@ class SingleInheritanceTest(MappedTest):
# session.query(Employee.name, Manager.manager_data, Engineer.engineer_info).all(),
# []
# )
+
+ @testing.resolve_artifact_names
+ def test_from_self(self):
+ sess = create_session()
+ self.assert_compile(sess.query(Engineer).from_self(),
+ 'SELECT anon_1.employees_employee_id AS '
+ 'anon_1_employees_employee_id, '
+ 'anon_1.employees_name AS '
+ 'anon_1_employees_name, '
+ 'anon_1.employees_manager_data AS '
+ 'anon_1_employees_manager_data, '
+ 'anon_1.employees_engineer_info AS '
+ 'anon_1_employees_engineer_info, '
+ 'anon_1.employees_type AS '
+ 'anon_1_employees_type FROM (SELECT '
+ 'employees.employee_id AS '
+ 'employees_employee_id, employees.name AS '
+ 'employees_name, employees.manager_data AS '
+ 'employees_manager_data, '
+ 'employees.engineer_info AS '
+ 'employees_engineer_info, employees.type '
+ 'AS employees_type FROM employees) AS '
+ 'anon_1 WHERE anon_1.employees_type IN '
+ '(:type_1, :type_2)',
+ use_default_dialect=True)
@testing.resolve_artifact_names
def test_select_from(self):
@@ -182,6 +208,54 @@ class SingleInheritanceTest(MappedTest):
assert len(rq.join(Report.employee.of_type(Manager)).all()) == 1
assert len(rq.join(Report.employee.of_type(Engineer)).all()) == 0
+class RelationshipFromSingleTest(testing.AssertsCompiledSQL, MappedTest):
+ @classmethod
+ def define_tables(cls, metadata):
+ Table('employee', metadata,
+ Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
+ Column('name', String(50)),
+ Column('type', String(20)),
+ )
+
+ Table('employee_stuff', metadata,
+ Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
+ Column('employee_id', Integer, ForeignKey('employee.id')),
+ Column('name', String(50)),
+ )
+
+ @classmethod
+ def setup_classes(cls):
+ class Employee(ComparableEntity):
+ pass
+ class Manager(Employee):
+ pass
+ class Stuff(ComparableEntity):
+ pass
+
+ @testing.resolve_artifact_names
+ def test_subquery_load(self):
+ mapper(Employee, employee, polymorphic_on=employee.c.type, polymorphic_identity='employee')
+ mapper(Manager, inherits=Employee, polymorphic_identity='manager', properties={
+ 'stuff':relationship(Stuff)
+ })
+ mapper(Stuff, employee_stuff)
+
+ sess = create_session()
+ context = sess.query(Manager).options(subqueryload('stuff'))._compile_context()
+ subq = context.attributes[('subquery', (class_mapper(Employee), 'stuff'))]
+
+ self.assert_compile(subq,
+ 'SELECT employee_stuff.id AS '
+ 'employee_stuff_id, employee_stuff.employee'
+ '_id AS employee_stuff_employee_id, '
+ 'employee_stuff.name AS '
+ 'employee_stuff_name, anon_1.employee_id '
+ 'AS anon_1_employee_id FROM (SELECT '
+ 'employee.id AS employee_id FROM employee '
+ 'WHERE employee.type IN (?)) AS anon_1 '
+ 'JOIN employee_stuff ON anon_1.employee_id '
+ '= employee_stuff.employee_id ORDER BY '
+ 'anon_1.employee_id')
class RelationshipToSingleTest(MappedTest):
@classmethod