- 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.
This commit is contained in:
Mike Bayer
2010-09-13 22:55:54 -04:00
parent 2ed6f06329
commit 03523970d9
4 changed files with 99 additions and 4 deletions
+11
View File
@@ -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
+12 -3
View File
@@ -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
+1
View File
@@ -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 = [
+75 -1
View File
@@ -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