summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/query.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm/query.py')
-rw-r--r--lib/sqlalchemy/orm/query.py60
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):