diff options
Diffstat (limited to 'lib/sqlalchemy/orm/query.py')
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 42f1b2673..6d2b144e3 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -879,32 +879,68 @@ class Query(object): """ return self._get_impl( - ident, loading.load_on_ident) + ident, loading.load_on_pk_identity) - def _get_impl(self, ident, fallback_fn, identity_token=None): + @classmethod + def _identity_lookup( + cls, session, mapper, primary_key_identity, identity_token=None, + passive=attributes.PASSIVE_OFF): + """Locate an object in the identity map. + + Given a primary key identity, constructs an identity key and then + looks in the session's identity map. If present, the object may + be run through unexpiration rules (e.g. load unloaded attributes, + check if was deleted). + + :param session: Session in use + :param mapper: target mapper + :param primary_key_identity: the primary key we are searching for, as + a tuple. + :param identity_token: identity token that should be used to create + the identity key. Used as is, however overriding subclasses can + repurpose this in order to interpret the value in a special way, + such as if None then look among multple target tokens. + :param passive: passive load flag passed to + :func:`.loading.get_from_identity`, which impacts the behavior if + the object is found; the object may be validated and/or unexpired + if the flag allows for SQL to be emitted. + :return: None if the object is not found in the identity map, *or* + if the object was unexpired and found to have been deleted. + if passive flags disallow SQL and the object is expired, returns + PASSIVE_NO_RESULT. In all other cases the instance is returned. + + .. versionadded:: 1.2.7 + + """ + key = mapper.identity_key_from_primary_key( + primary_key_identity, identity_token=identity_token) + return loading.get_from_identity( + session, key, passive) + + def _get_impl( + self, primary_key_identity, db_load_fn, identity_token=None): # convert composite types to individual args - if hasattr(ident, '__composite_values__'): - ident = ident.__composite_values__() + if hasattr(primary_key_identity, '__composite_values__'): + primary_key_identity = primary_key_identity.__composite_values__() - ident = util.to_list(ident) + primary_key_identity = util.to_list(primary_key_identity) mapper = self._only_full_mapper_zero("get") - if len(ident) != len(mapper.primary_key): + if len(primary_key_identity) != len(mapper.primary_key): raise sa_exc.InvalidRequestError( "Incorrect number of values in identifier to formulate " "primary key for query.get(); primary key columns are %s" % ','.join("'%s'" % c for c in mapper.primary_key)) - key = mapper.identity_key_from_primary_key( - ident, identity_token=identity_token) - if not self._populate_existing and \ not mapper.always_refresh and \ self._for_update_arg is None: - instance = loading.get_from_identity( - self.session, key, attributes.PASSIVE_OFF) + instance = self._identity_lookup( + self.session, mapper, primary_key_identity, + identity_token=identity_token) + if instance is not None: self._get_existing_condition() # reject calls for id in identity map but class @@ -913,7 +949,7 @@ class Query(object): return None return instance - return fallback_fn(self, key) + return db_load_fn(self, primary_key_identity) @_generative() def correlate(self, *args): |
