summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/mapper.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm/mapper.py')
-rw-r--r--lib/sqlalchemy/orm/mapper.py73
1 files changed, 43 insertions, 30 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 2ec30f0ba..789f29c73 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -28,7 +28,8 @@ from sqlalchemy.orm.interfaces import MapperProperty, EXT_CONTINUE, \
PropComparator
from sqlalchemy.orm.util import _INSTRUMENTOR, _class_to_mapper, \
- _state_mapper, class_mapper, instance_str, state_str
+ _state_mapper, class_mapper, instance_str, state_str,\
+ PathRegistry
import sys
sessionlib = util.importlater("sqlalchemy.orm", "session")
@@ -432,6 +433,10 @@ class Mapper(object):
dispatch = event.dispatcher(events.MapperEvents)
+ @util.memoized_property
+ def _sa_path_registry(self):
+ return PathRegistry.per_mapper(self)
+
def _configure_inheritance(self):
"""Configure settings related to inherting and/or inherited mappers
being present."""
@@ -1302,13 +1307,12 @@ class Mapper(object):
return mappers
- def _selectable_from_mappers(self, mappers):
+ def _selectable_from_mappers(self, mappers, innerjoin):
"""given a list of mappers (assumed to be within this mapper's
inheritance hierarchy), construct an outerjoin amongst those mapper's
mapped tables.
"""
-
from_obj = self.mapped_table
for m in mappers:
if m is self:
@@ -1318,7 +1322,11 @@ class Mapper(object):
"'with_polymorphic()' requires 'selectable' argument "
"when concrete-inheriting mappers are used.")
elif not m.single:
- from_obj = from_obj.outerjoin(m.local_table,
+ if innerjoin:
+ from_obj = from_obj.join(m.local_table,
+ m.inherit_condition)
+ else:
+ from_obj = from_obj.outerjoin(m.local_table,
m.inherit_condition)
return from_obj
@@ -1350,9 +1358,11 @@ class Mapper(object):
return selectable
else:
return self._selectable_from_mappers(
- self._mappers_from_spec(spec, selectable))
+ self._mappers_from_spec(spec, selectable),
+ False)
- def _with_polymorphic_args(self, spec=None, selectable=False):
+ def _with_polymorphic_args(self, spec=None, selectable=False,
+ innerjoin=False):
if self.with_polymorphic:
if not spec:
spec = self.with_polymorphic[0]
@@ -1364,7 +1374,8 @@ class Mapper(object):
if selectable is not None:
return mappers, selectable
else:
- return mappers, self._selectable_from_mappers(mappers)
+ return mappers, self._selectable_from_mappers(mappers,
+ innerjoin)
@_memoized_configured_property
def _polymorphic_properties(self):
@@ -1926,7 +1937,7 @@ class Mapper(object):
return result
- def _instance_processor(self, context, path, reduced_path, adapter,
+ def _instance_processor(self, context, path, adapter,
polymorphic_from=None,
only_load_props=None, refresh_state=None,
polymorphic_discriminator=None):
@@ -1951,7 +1962,7 @@ class Mapper(object):
polymorphic_on = self.polymorphic_on
polymorphic_instances = util.PopulateDict(
self._configure_subclass_mapper(
- context, path, reduced_path, adapter)
+ context, path, adapter)
)
version_id_col = self.version_id_col
@@ -1968,7 +1979,9 @@ class Mapper(object):
new_populators = []
existing_populators = []
eager_populators = []
- load_path = context.query._current_path + path
+ load_path = context.query._current_path + path \
+ if context.query._current_path.path \
+ else path
def populate_state(state, dict_, row, isnew, only_load_props):
if isnew:
@@ -1978,7 +1991,7 @@ class Mapper(object):
state.load_path = load_path
if not new_populators:
- self._populators(context, path, reduced_path, row, adapter,
+ self._populators(context, path, row, adapter,
new_populators,
existing_populators,
eager_populators
@@ -2015,7 +2028,7 @@ class Mapper(object):
def _instance(row, result):
if not new_populators and invoke_all_eagers:
- self._populators(context, path, reduced_path, row, adapter,
+ self._populators(context, path, row, adapter,
new_populators,
existing_populators,
eager_populators
@@ -2191,16 +2204,17 @@ class Mapper(object):
return instance
return _instance
- def _populators(self, context, path, reduced_path, row, adapter,
+ def _populators(self, context, path, row, adapter,
new_populators, existing_populators, eager_populators):
- """Produce a collection of attribute level row processor callables."""
+ """Produce a collection of attribute level row processor
+ callables."""
delayed_populators = []
- pops = (new_populators, existing_populators, delayed_populators, eager_populators)
+ pops = (new_populators, existing_populators, delayed_populators,
+ eager_populators)
for prop in self._props.itervalues():
for i, pop in enumerate(prop.create_row_processor(
- context, path,
- reduced_path,
+ context, path,
self, row, adapter)):
if pop is not None:
pops[i].append((prop.key, pop))
@@ -2208,7 +2222,7 @@ class Mapper(object):
if delayed_populators:
new_populators.extend(delayed_populators)
- def _configure_subclass_mapper(self, context, path, reduced_path, adapter):
+ def _configure_subclass_mapper(self, context, path, adapter):
"""Produce a mapper level row processor callable factory for mappers
inheriting this one."""
@@ -2223,18 +2237,17 @@ class Mapper(object):
return None
# replace the tip of the path info with the subclass mapper
- # being used. that way accurate "load_path" info is available
- # for options invoked during deferred loads.
- # we lose AliasedClass path elements this way, but currently,
- # those are not needed at this stage.
-
- # this asserts to true
- #assert mapper.isa(_class_to_mapper(path[-1]))
-
- return mapper._instance_processor(context, path[0:-1] + (mapper,),
- reduced_path[0:-1] + (mapper.base_mapper,),
- adapter,
- polymorphic_from=self)
+ # being used, that way accurate "load_path" info is available
+ # for options invoked during deferred loads, e.g.
+ # query(Person).options(defer(Engineer.machines, Machine.name)).
+ # for AliasedClass paths, disregard this step (new in 0.8).
+ return mapper._instance_processor(
+ context,
+ path.parent[mapper]
+ if not path.is_aliased_class
+ else path,
+ adapter,
+ polymorphic_from=self)
return configure_subclass_mapper
log.class_logger(Mapper)