self._process(query, False)
def _process(self, query, raiseerr):
- paths = self.__get_paths(query, raiseerr)
+ paths, mappers = self.__get_paths(query, raiseerr)
if paths:
- self.process_query_property(query, paths)
+ self.process_query_property(query, paths, mappers)
- def process_query_property(self, query, paths):
+ def process_query_property(self, query, paths, mappers):
pass
def __find_entity(self, query, mapper, raiseerr):
path = None
entity = None
l = []
-
+ mappers = []
+
# _current_path implies we're in a secondary load
# with an existing path
current_path = list(query._current_path)
entity = query._entity_zero()
path_element = entity.path_entity
mapper = entity.mapper
+ mappers.append(mapper)
prop = mapper.get_property(token, resolve_synonyms=True, raiseerr=raiseerr)
key = token
elif isinstance(token, PropComparator):
if not entity:
entity = self.__find_entity(query, token.parententity, raiseerr)
if not entity:
- return []
+ return [], []
path_element = entity.path_entity
+ mappers.append(prop.parent)
key = prop.key
else:
raise sa_exc.ArgumentError("mapper option expects string key or list of attributes")
continue
if prop is None:
- return []
+ return [], []
path = build_path(path_element, prop.key, path)
l.append(path)
path_element = mapper = token._of_type
else:
path_element = mapper = getattr(prop, 'mapper', None)
+
if path_element:
path_element = path_element.base_mapper
-
+
+
# if current_path tokens remain, then
# we didn't have an exact path match.
if current_path:
- return []
+ return [], []
- return l
+ return l, mappers
class AttributeExtension(object):
"""An event handler for individual attribute change events.
def is_chained(self):
return False
- def process_query_property(self, query, paths):
+ def process_query_property(self, query, paths, mappers):
if self.is_chained():
for path in paths:
query._attributes[("loaderstrategy", path)] = self.get_strategy_class()
eq_(node, B(id=1, name='b1',b_data='i'))
eq_(node.children[0], B(id=2, name='b2',b_data='l'))
-class EagerToSubclassTest(_base.MappedTest):
- """Test eagerloads to subclass mappers"""
-
- run_setup_classes = 'once'
- run_setup_mappers = 'once'
- run_inserts = 'once'
- run_deletes = None
-
- @classmethod
- def define_tables(cls, metadata):
- Table('parent', metadata,
- Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
- Column('data', String(10)),
- )
-
- Table('base', metadata,
- Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
- Column('type', String(10)),
- )
-
- Table('sub', metadata,
- Column('id', Integer, ForeignKey('base.id'), primary_key=True),
- Column('data', String(10)),
- Column('parent_id', Integer, ForeignKey('parent.id'), nullable=False)
- )
-
- @classmethod
- @testing.resolve_artifact_names
- def setup_classes(cls):
- class Parent(_base.ComparableEntity):
- pass
-
- class Base(_base.ComparableEntity):
- pass
-
- class Sub(Base):
- pass
-
- @classmethod
- @testing.resolve_artifact_names
- def setup_mappers(cls):
- mapper(Parent, parent, properties={
- 'children':relation(Sub)
- })
- mapper(Base, base, polymorphic_on=base.c.type, polymorphic_identity='b')
- mapper(Sub, sub, inherits=Base, polymorphic_identity='s')
-
- @classmethod
- @testing.resolve_artifact_names
- def insert_data(cls):
- sess = create_session()
- p1 = Parent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')])
- p2 = Parent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
- sess.add(p1)
- sess.add(p2)
- sess.flush()
-
- @testing.resolve_artifact_names
- def test_eagerload(self):
- sess = create_session()
- def go():
- eq_(
- sess.query(Parent).options(eagerload(Parent.children)).all(),
- [
- Parent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
- Parent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
- ]
- )
- self.assert_sql_count(testing.db, go, 1)
-
- @testing.resolve_artifact_names
- def test_contains_eager(self):
- sess = create_session()
- def go():
- eq_(
- sess.query(Parent).join(Parent.children).options(contains_eager(Parent.children)).all(),
- [
- Parent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
- Parent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
- ]
- )
- self.assert_sql_count(testing.db, go, 1)
-
class FlushTest(_base.MappedTest):
"""test dependency sorting among inheriting mappers"""
@classmethod
assert q.first() is c1
+class EagerToSubclassTest(_base.MappedTest):
+ """Test eagerloads to subclass mappers"""
+
+ run_setup_classes = 'once'
+ run_setup_mappers = 'once'
+ run_inserts = 'once'
+ run_deletes = None
+
+ @classmethod
+ def define_tables(cls, metadata):
+ Table('parent', metadata,
+ Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
+ Column('data', String(10)),
+ )
+
+ Table('base', metadata,
+ Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
+ Column('type', String(10)),
+ )
+
+ Table('sub', metadata,
+ Column('id', Integer, ForeignKey('base.id'), primary_key=True),
+ Column('data', String(10)),
+ Column('parent_id', Integer, ForeignKey('parent.id'), nullable=False)
+ )
+
+ @classmethod
+ @testing.resolve_artifact_names
+ def setup_classes(cls):
+ class Parent(_base.ComparableEntity):
+ pass
+
+ class Base(_base.ComparableEntity):
+ pass
+
+ class Sub(Base):
+ pass
+
+ @classmethod
+ @testing.resolve_artifact_names
+ def setup_mappers(cls):
+ mapper(Parent, parent, properties={
+ 'children':relation(Sub)
+ })
+ mapper(Base, base, polymorphic_on=base.c.type, polymorphic_identity='b')
+ mapper(Sub, sub, inherits=Base, polymorphic_identity='s')
+
+ @classmethod
+ @testing.resolve_artifact_names
+ def insert_data(cls):
+ sess = create_session()
+ p1 = Parent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')])
+ p2 = Parent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ sess.add(p1)
+ sess.add(p2)
+ sess.flush()
+
+ @testing.resolve_artifact_names
+ def test_eagerload(self):
+ sess = create_session()
+ def go():
+ eq_(
+ sess.query(Parent).options(eagerload(Parent.children)).all(),
+ [
+ Parent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
+ Parent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ ]
+ )
+ self.assert_sql_count(testing.db, go, 1)
+
+ @testing.resolve_artifact_names
+ def test_contains_eager(self):
+ sess = create_session()
+ def go():
+ eq_(
+ sess.query(Parent).join(Parent.children).options(contains_eager(Parent.children)).all(),
+ [
+ Parent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
+ Parent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ ]
+ )
+ self.assert_sql_count(testing.db, go, 1)
+
+class SubClassEagerToSubclassTest(_base.MappedTest):
+ """Test eagerloads from subclass to subclass mappers"""
+
+ run_setup_classes = 'once'
+ run_setup_mappers = 'once'
+ run_inserts = 'once'
+ run_deletes = None
+
+ @classmethod
+ def define_tables(cls, metadata):
+ Table('parent', metadata,
+ Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
+ Column('type', String(10)),
+ )
+
+ Table('subparent', metadata,
+ Column('id', Integer, ForeignKey('parent.id'), primary_key=True),
+ Column('data', String(10)),
+ )
+
+ Table('base', metadata,
+ Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
+ Column('type', String(10)),
+ )
+
+ Table('sub', metadata,
+ Column('id', Integer, ForeignKey('base.id'), primary_key=True),
+ Column('data', String(10)),
+ Column('subparent_id', Integer, ForeignKey('subparent.id'), nullable=False)
+ )
+
+ @classmethod
+ @testing.resolve_artifact_names
+ def setup_classes(cls):
+ class Parent(_base.ComparableEntity):
+ pass
+
+ class Subparent(Parent):
+ pass
+
+ class Base(_base.ComparableEntity):
+ pass
+
+ class Sub(Base):
+ pass
+
+ @classmethod
+ @testing.resolve_artifact_names
+ def setup_mappers(cls):
+ mapper(Parent, parent, polymorphic_on=parent.c.type, polymorphic_identity='b')
+ mapper(Subparent, subparent, inherits=Parent, polymorphic_identity='s', properties={
+ 'children':relation(Sub)
+ })
+ mapper(Base, base, polymorphic_on=base.c.type, polymorphic_identity='b')
+ mapper(Sub, sub, inherits=Base, polymorphic_identity='s')
+
+ @classmethod
+ @testing.resolve_artifact_names
+ def insert_data(cls):
+ sess = create_session()
+ p1 = Subparent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')])
+ p2 = Subparent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ sess.add(p1)
+ sess.add(p2)
+ sess.flush()
+
+ @testing.resolve_artifact_names
+ def test_eagerload(self):
+ sess = create_session()
+ def go():
+ eq_(
+ sess.query(Subparent).options(eagerload(Subparent.children)).all(),
+ [
+ Subparent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
+ Subparent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ ]
+ )
+ self.assert_sql_count(testing.db, go, 1)
+
+ sess.expunge_all()
+ def go():
+ eq_(
+ sess.query(Subparent).options(eagerload("children")).all(),
+ [
+ Subparent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
+ Subparent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ ]
+ )
+ self.assert_sql_count(testing.db, go, 1)
+
+ @testing.resolve_artifact_names
+ def test_contains_eager(self):
+ sess = create_session()
+ def go():
+ eq_(
+ sess.query(Subparent).join(Subparent.children).options(contains_eager(Subparent.children)).all(),
+ [
+ Subparent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
+ Subparent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ ]
+ )
+ self.assert_sql_count(testing.db, go, 1)
+ sess.expunge_all()
+
+ def go():
+ eq_(
+ sess.query(Subparent).join(Subparent.children).options(contains_eager("children")).all(),
+ [
+ Subparent(data='p1', children=[Sub(data='s1'), Sub(data='s2'), Sub(data='s3')]),
+ Subparent(data='p2', children=[Sub(data='s4'), Sub(data='s5')])
+ ]
+ )
+ self.assert_sql_count(testing.db, go, 1)
+
+