diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-09-30 21:26:08 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-10-01 16:11:34 -0400 |
| commit | 9a2a0f324c13b5a1b334a3982a766cb9f21f428e (patch) | |
| tree | f4548faa2cf60f07d2e13e6eb1b137ff1d3e072d /lib/sqlalchemy | |
| parent | a3c964203e61f8deeb559b15a78cc640dee67012 (diff) | |
| download | sqlalchemy-9a2a0f324c13b5a1b334a3982a766cb9f21f428e.tar.gz | |
Cancel polymorphic loading in optimized get
Since optimized_get for inheriting mappers writes a simple
SELECT, we need to cancel out any with_polymorphic selectables
that interfere with simple column lookup. While adaptation is
another option, just removing the with_polymorphic is much
simpler. The issue is not noticeable unless the ResultProxy
is not allowing "key fallback" column lookups, which will
be the case when this behavior is deprecated.
Fixes: #4718
Change-Id: I8fa2f5c0434b6a681813a92ac71fe12712f5d634
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/loading.py | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 5 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/util.py | 2 |
4 files changed, 11 insertions, 4 deletions
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py index 94a9b8d22..886240591 100644 --- a/lib/sqlalchemy/orm/loading.py +++ b/lib/sqlalchemy/orm/loading.py @@ -23,6 +23,7 @@ from . import strategy_options from .base import _DEFER_FOR_STATE from .base import _SET_DEFERRED_EXPIRED from .util import _none_set +from .util import aliased from .util import state_str from .. import exc as sa_exc from .. import util @@ -633,7 +634,6 @@ def _instance_processor( if mapper.polymorphic_map and not _polymorphic_from and not refresh_state: # if we are doing polymorphic, dispatch to a different _instance() # method specific to the subclass mapper - def ensure_no_pk(row): identitykey = ( identity_class, @@ -957,9 +957,10 @@ def load_scalar_attributes(mapper, state, attribute_names): # by default statement = mapper._optimized_get_statement(state, attribute_names) if statement is not None: + wp = aliased(mapper, statement) result = load_on_ident( - session.query(mapper) - .options(strategy_options.Load(mapper).undefer("*")) + session.query(wp) + .options(strategy_options.Load(wp).undefer("*")) .from_statement(statement), None, only_load_props=attribute_names, diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 3d08dce22..0480bfb01 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -774,6 +774,11 @@ class Query(Generative): ) entity = self._entities[0]._clone() self._entities = [entity] + self._entities[1:] + + # NOTE: we likely should set primary_entity here, however + # this hasn't been changed for many years and we'd like to + # deprecate this method. + entity.set_with_polymorphic( self, cls_or_mappers, diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 1f2f65728..1c7c0546d 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -183,7 +183,6 @@ class ColumnLoader(LoaderStrategy): memoized_populators, **kwargs ): - for c in self.columns: if adapter: c = adapter.columns[c] diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 3c7f904de..780cdc7b2 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -798,6 +798,8 @@ class ClauseAdapter(visitors.ReplacingCloningVisitor): if newcol is not None: return newcol if self.adapt_on_names and newcol is None: + # TODO: this should be changed to .exported_columns if and + # when we need to be able to adapt a plain Select statement newcol = self.selectable.c.get(col.name) return newcol |
