summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-02-28 21:16:34 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2015-02-28 21:16:34 -0500
commit9cddb2afa2009c128b960971c1eac2030bc028f1 (patch)
treeeac7e2838d2566cdae8ac2f30530c85d0265910d
parent43289c86134108f2c99ab0d3a006eda161c310fa (diff)
downloadsqlalchemy-row_proc_integration_2.tar.gz
- sort of working, not saving on much, eager loading of courserow_proc_integration_2
totally broken.
-rw-r--r--lib/sqlalchemy/orm/loading.py85
-rw-r--r--lib/sqlalchemy/orm/query.py86
-rw-r--r--lib/sqlalchemy/orm/strategies.py49
-rw-r--r--lib/sqlalchemy/sql/util.py6
4 files changed, 105 insertions, 121 deletions
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index aca6ad60b..752ec745d 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -29,9 +29,6 @@ def instances(query, cursor, context):
context.runid = _new_runid()
- if context.outer_adapter:
- context.outer_adapter._adapt_to_resultproxy(cursor)
-
filter_fns = [ent.filter_fn for ent in query._entities]
filtered = id in filter_fns
@@ -46,21 +43,12 @@ def instances(query, cursor, context):
return tuple(fn(x) for x, fn in zip(row, filter_fns))
try:
- if context._predefined_statement:
- labels, process = list(zip(
- *[
- entity.create_row_processor(context, cursor, None)
- for entity in query._entities
- ]
- ))
- else:
- labels, process = list(zip(
- *[
- entity.create_row_processor(context, cursor, loader)
- for entity, loader
- in zip(query._entities, context.loaders)
- ]
- ))
+ labels, process = list(zip(
+ *[
+ entity.row_processor(query, context, cursor)
+ for entity in query._entities
+ ]
+ ))
if not single_entity:
# TODO: this should be in context, so it can also be cached.
@@ -232,11 +220,10 @@ def load_on_ident(query, key,
def _instance_processor(
- mapper, context,
- query_entity, path, adapter,
- props_toload=None,
- column_collection=None, result=None,
+ mapper, context, result,
+ path, adapter,
only_load_props=None, refresh_state=None,
+ quick_populators=None,
polymorphic_discriminator=None,
_polymorphic_from=None):
"""Produce a mapper level row processor callable
@@ -246,20 +233,6 @@ def _instance_processor(
populators = collections.defaultdict(list)
- if props_toload:
- for prop in props_toload:
-
- prop.setup(
- context,
- query_entity,
- path,
- mapper,
- adapter,
- column_collection,
- populators,
- only_load_props=only_load_props,
- )
-
pk_cols = mapper.primary_key
if adapter:
@@ -410,27 +383,31 @@ def _instance_processor(
# if we are doing polymorphic, dispatch to a different _instance()
# method specific to the subclass mapper
_instance = _decorate_polymorphic_switch(
- _instance, context, mapper, query_entity, path,
+ _instance, result, context, mapper, path,
polymorphic_discriminator, adapter)
- if result is not None:
- props = mapper._props.values()
+ props = mapper._props.values()
+ if False: #quick_populators:
+ populators["quick"] = [
+ (key, result._getter(col))
+ for key, col in quick_populators["quick"].items()
+ ]
+ for prop in props:
+ if prop.key in populators["row_processor"]:
+ strategy, local_populators = \
+ populators["row_processor"][prop.key]
+ prop.create_row_processor(
+ result, context, path, mapper, adapter, populators,
+ quick_populators=local_populators
+ )
+ else:
if only_load_props is not None:
props = (p for p in props if p.key in only_load_props)
-
for prop in props:
prop.create_row_processor(
result,
context, path, mapper, adapter, populators)
- return _instance
-
- def setup_result(result):
- populators["quick"] = [
- (key, result._getter(col)) for key, col in populators["quick"]
- ]
- return _instance
-
- return setup_result
+ return _instance
def _populate_full(
@@ -515,7 +492,7 @@ def _validate_version_id(mapper, state, dict_, row, adapter):
def _decorate_polymorphic_switch(
- instance_fn, context, mapper, query_entity,
+ instance_fn, result, context, mapper,
path, polymorphic_discriminator, adapter):
if polymorphic_discriminator is not None:
@@ -531,8 +508,6 @@ def _decorate_polymorphic_switch(
if polymorphic_discriminator is not mapper.polymorphic_on:
context.primary_columns.append(polymorphic_on)
- result = []
-
def configure_subclass_mapper(discriminator):
try:
sub_mapper = mapper.polymorphic_map[discriminator]
@@ -545,8 +520,8 @@ def _decorate_polymorphic_switch(
return None
return _instance_processor(
- sub_mapper, context,
- query_entity, path, adapter, result=result[0],
+ sub_mapper, context, result,
+ path, adapter,
_polymorphic_from=mapper)
polymorphic_instances = util.PopulateDict(
@@ -554,8 +529,6 @@ def _decorate_polymorphic_switch(
)
def polymorphic_instance(row):
- if not result:
- result.append(row)
discriminator = row[polymorphic_on]
if discriminator is not None:
_instance = polymorphic_instances[discriminator]
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index d039b28e9..6f01b7753 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -20,6 +20,7 @@ database to return iterable result sets.
"""
from __future__ import absolute_import
+import collections
import operator
from itertools import chain
@@ -3295,26 +3296,43 @@ class _MapperEntity(_QueryEntity):
else:
only_load_props = refresh_state = None
- _instance = loading._instance_processor(
- self.mapper,
- context,
- self,
- self.path,
- adapter,
- props_toload=props_toload,
- column_collection=context.primary_columns,
- only_load_props=only_load_props,
- refresh_state=refresh_state,
- polymorphic_discriminator=self._polymorphic_discriminator
+ quick_populators = {
+ "quick": {},
+ "row_processor": {}
+ }
+
+ for prop in props_toload:
+
+ prop.setup(
+ context,
+ self,
+ self.path,
+ self.mapper,
+ adapter,
+ context.primary_columns,
+ quick_populators,
+ refresh_state=refresh_state,
+ only_load_props=only_load_props,
+ )
+
+ context.attributes[(self, "memoized_setup")] = (
+ quick_populators,
+ adapter
)
- context.loaders.append(_instance)
+ def row_processor(self, query, context, result):
- def create_row_processor(self, context, result, loader):
- if loader is not None:
- return self._label_name, loader(result)
+ key = (self, "memoized_setup")
+ if key in context.attributes:
+ quick_populators, adapter = context.attributes[key]
+ else:
+ quick_populators = None
+ adapter = self._get_entity_clauses(context.query, context)
- adapter = self._get_entity_clauses(context.query, context)
+ if context.outer_adapter and adapter:
+ adapter = adapter.wrap(context.outer_adapter)
+ elif not adapter:
+ adapter = context.outer_adapter
if context.query._primary_entity is self:
only_load_props = context.query._only_load_props
@@ -3325,10 +3343,10 @@ class _MapperEntity(_QueryEntity):
_instance = loading._instance_processor(
self.mapper,
context,
- self,
+ result,
self.path,
adapter,
- result=result,
+ quick_populators=quick_populators,
only_load_props=only_load_props,
refresh_state=refresh_state,
polymorphic_discriminator=self._polymorphic_discriminator
@@ -3510,23 +3528,20 @@ class _BundleEntity(_QueryEntity):
for ent in self._entities:
ent.setup_entity(ext_info, aliased_adapter)
- def setup_context(self, query, context, loaders=None):
-
- our_loaders = []
+ def setup_context(self, query, context):
for ent in self._entities:
- ent.setup_context(
- query, context, loaders=our_loaders)
+ ent.setup_context(query, context)
+
+ def row_processor(self, query, context, result):
labels, procs = zip(
- *our_loaders
+ *[ent.row_processor(query, context, result)
+ for ent in self._entities]
)
- proc = self.bundle.create_row_processor(query, procs, labels)
+ proc = self.bundle.create_row_processor(context.query, procs, labels)
- if loaders is not None:
- loaders.append((self._label_name, proc))
- else:
- context.loaders.append((self._label_name, proc))
+ return self._label_name, proc
class _ColumnEntity(_QueryEntity):
@@ -3664,14 +3679,12 @@ class _ColumnEntity(_QueryEntity):
query, self.column, context)
context.froms += tuple(self.froms)
context.primary_columns.append(column)
- context.loaders.append(column)
+ if loaders is not None:
+ loaders.append(column)
- def create_row_processor(self, context, result, loader):
- if loader is None:
- column = self._resolve_expr_against_query_aliases(
- context.query, self.column, context)
- else:
- column = loader
+ def row_processor(self, query, context, result):
+ column = self._resolve_expr_against_query_aliases(
+ context.query, self.column, context)
getter = result._getter(column)
return self._label_name, getter
@@ -3716,7 +3729,6 @@ class QueryContext(object):
self.propagate_options = set(o for o in query._with_options if
o.propagate_to_loaders)
self.attributes = query._attributes.copy()
- self.loaders = []
class AliasOption(interfaces.MapperOption):
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index a3885d3e0..059e2d1f7 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -24,7 +24,6 @@ from .interfaces import (
)
from .session import _state_session
-import operator
import itertools
@@ -136,7 +135,7 @@ class ColumnLoader(LoaderStrategy):
def setup_query(
self, context, query_entity, path, mapper,
- adapter, column_collection, populators, loadopt, **kw):
+ adapter, column_collection, quick_populators, loadopt, **kw):
for c in self.columns:
if adapter:
c = adapter.columns[c]
@@ -149,9 +148,7 @@ class ColumnLoader(LoaderStrategy):
# should be added here so that we need not bother
# querying out every column.
- populators["quick"].append(
- (self.key, self.columns[0])
- )
+ quick_populators["quick"][self.key] = self.columns[0]
def create_row_processor(
self, result, context, path,
@@ -244,7 +241,7 @@ class DeferredColumnLoader(LoaderStrategy):
if adapter:
col = adapter.columns[col]
- getter = context._getter(col, result)
+ getter = result._getter(col)
if getter:
self.parent_property._get_strategy_by_cls(ColumnLoader).\
create_row_processor(
@@ -1111,10 +1108,12 @@ class JoinedLoader(AbstractRelationshipLoader):
_get_strategy_by_cls(LazyLoader).init_class_attribute(mapper)
def setup_query(
- self, context, entity, path, loadopt, adapter,
- column_collection=None, parentmapper=None,
+ self, context, query_entity, path, mapper,
+ adapter, column_collection, quick_populators, loadopt,
+ parentmapper=None,
chained_from_outerjoin=False,
- **kwargs):
+ **kw):
+
"""Add a left outer join to the statement that's being constructed."""
if not context.query._enable_eagerloads:
@@ -1132,7 +1131,7 @@ class JoinedLoader(AbstractRelationshipLoader):
if user_defined_adapter is not False:
clauses, adapter, add_to_collection = \
self._setup_query_on_user_defined_adapter(
- context, entity, path, adapter,
+ context, query_entity, path, adapter,
user_defined_adapter
)
else:
@@ -1147,7 +1146,7 @@ class JoinedLoader(AbstractRelationshipLoader):
clauses, adapter, add_to_collection, chained_from_outerjoin = \
self._generate_row_adapter(
- context, entity, path, loadopt, adapter,
+ context, query_entity, path, loadopt, adapter,
column_collection, parentmapper, chained_from_outerjoin
)
@@ -1163,17 +1162,28 @@ class JoinedLoader(AbstractRelationshipLoader):
path = path[self.mapper]
- for value in self.mapper._iterate_polymorphic_properties(
+ _local_quick_populators = {
+ "quick": {},
+ "row_processor": {}
+ }
+
+ for prop in self.mapper._iterate_polymorphic_properties(
mappers=with_polymorphic):
- value.setup(
+
+ prop.setup(
context,
- entity,
+ query_entity,
path,
+ self.mapper,
clauses,
+ add_to_collection,
+ _local_quick_populators,
parentmapper=self.mapper,
- column_collection=add_to_collection,
chained_from_outerjoin=chained_from_outerjoin)
+ #quick_populators["row_processor"][self.key] = \
+ # self, _local_quick_populators
+
if with_poly_info is not None and \
None in set(context.secondary_columns):
raise sa_exc.InvalidRequestError(
@@ -1205,11 +1215,6 @@ class JoinedLoader(AbstractRelationshipLoader):
root_mapper, prop = path[-2:]
- #from .mapper import Mapper
- #from .interfaces import MapperProperty
- #assert isinstance(root_mapper, Mapper)
- #assert isinstance(prop, MapperProperty)
-
if alias is not None:
if isinstance(alias, str):
alias = prop.target.alias(alias)
@@ -1479,8 +1484,8 @@ class JoinedLoader(AbstractRelationshipLoader):
else:
self.parent_property._get_strategy_by_cls(LazyLoader).\
create_row_processor(
- result, context, path, loadopt,
- mapper, adapter, populators)
+ result, context, path,
+ mapper, adapter, populators, loadopt, **kw)
def _create_collection_loader(self, context, key, _instance, populators):
def load_collection_from_joined_new_row(state, dict_, row):
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py
index 0bd65422f..fbbe15da3 100644
--- a/lib/sqlalchemy/sql/util.py
+++ b/lib/sqlalchemy/sql/util.py
@@ -600,12 +600,6 @@ class ColumnAdapter(ClauseAdapter):
return c
- def _adapt_to_resultproxy(self, result):
- keymap = result._metadata._keymap
-
- for col in self.selectable.c:
- keymap[col] = keymap[self.columns[col]]
-
def __getstate__(self):
d = self.__dict__.copy()
del d['columns']