diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-02-28 21:16:34 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-02-28 21:16:34 -0500 |
commit | 9cddb2afa2009c128b960971c1eac2030bc028f1 (patch) | |
tree | eac7e2838d2566cdae8ac2f30530c85d0265910d | |
parent | 43289c86134108f2c99ab0d3a006eda161c310fa (diff) | |
download | sqlalchemy-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.py | 85 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/query.py | 86 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 49 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/util.py | 6 |
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'] |