summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-06-04 17:29:20 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-10-01 16:52:24 -0400
commitcc718cccc0bf8a01abdf4068c7ea4f32c9322af6 (patch)
treee839526dd0ab64bf0d8babe01006e03987403a66 /lib/sqlalchemy/orm
parenta3c964203e61f8deeb559b15a78cc640dee67012 (diff)
downloadsqlalchemy-cc718cccc0bf8a01abdf4068c7ea4f32c9322af6.tar.gz
Run row value processors up front
as part of a larger series of changes to generalize row-tuples, RowProxy becomes plain Row and is no longer a "proxy"; the DBAPI row is now copied directly into the Row when constructed, result handling occurs at once. Subsequent changes will break out Row into a new version that behaves fully a tuple. Change-Id: I2ffa156afce5d21c38f28e54c3a531f361345dd5
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/loading.py21
-rw-r--r--lib/sqlalchemy/orm/strategies.py20
-rw-r--r--lib/sqlalchemy/orm/util.py4
3 files changed, 22 insertions, 23 deletions
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index 94a9b8d22..53b901689 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -358,11 +358,6 @@ def _instance_processor(
# call overhead. _instance() is the most
# performance-critical section in the whole ORM.
- pk_cols = mapper.primary_key
-
- if adapter:
- pk_cols = [adapter.columns[c] for c in pk_cols]
-
identity_class = mapper._identity_class
populators = collections.defaultdict(list)
@@ -488,6 +483,12 @@ def _instance_processor(
else:
refresh_identity_key = None
+ pk_cols = mapper.primary_key
+
+ if adapter:
+ pk_cols = [adapter.columns[c] for c in pk_cols]
+ tuple_getter = result._tuple_getter(pk_cols, True)
+
if mapper.allow_partial_pks:
is_not_primary_key = _none_set.issuperset
else:
@@ -507,11 +508,7 @@ def _instance_processor(
else:
# look at the row, see if that identity is in the
# session, or we have to create a new one
- identitykey = (
- identity_class,
- tuple([row[column] for column in pk_cols]),
- identity_token,
- )
+ identitykey = (identity_class, tuple_getter(row), identity_token)
instance = session_identity_map.get(identitykey)
@@ -853,8 +850,10 @@ def _decorate_polymorphic_switch(
polymorphic_instances = util.PopulateDict(configure_subclass_mapper)
+ getter = result._getter(polymorphic_on)
+
def polymorphic_instance(row):
- discriminator = row[polymorphic_on]
+ discriminator = getter(row)
if discriminator is not None:
_instance = polymorphic_instances[discriminator]
if _instance:
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 1f2f65728..d8e5997c1 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -1383,20 +1383,20 @@ class SubqueryLoader(PostLoader):
if self.uselist:
self._create_collection_loader(
- context, collections, local_cols, populators
+ context, result, collections, local_cols, populators
)
else:
self._create_scalar_loader(
- context, collections, local_cols, populators
+ context, result, collections, local_cols, populators
)
def _create_collection_loader(
- self, context, collections, local_cols, populators
+ self, context, result, collections, local_cols, populators
):
+ tuple_getter = result._tuple_getter(local_cols)
+
def load_collection_from_subq(state, dict_, row):
- collection = collections.get(
- tuple([row[col] for col in local_cols]), ()
- )
+ collection = collections.get(tuple_getter(row), ())
state.get_impl(self.key).set_committed_value(
state, dict_, collection
)
@@ -1414,12 +1414,12 @@ class SubqueryLoader(PostLoader):
populators["eager"].append((self.key, collections.loader))
def _create_scalar_loader(
- self, context, collections, local_cols, populators
+ self, context, result, collections, local_cols, populators
):
+ tuple_getter = result._tuple_getter(local_cols)
+
def load_scalar_from_subq(state, dict_, row):
- collection = collections.get(
- tuple([row[col] for col in local_cols]), (None,)
- )
+ collection = collections.get(tuple_getter(row), (None,))
if len(collection) > 1:
util.warn(
"Multiple rows returned with "
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 747ec7e65..5f0f41e8d 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -297,7 +297,7 @@ def identity_key(*args, **kwargs):
* ``identity_key(class, row=row, identity_token=token)``
This form is similar to the class/tuple form, except is passed a
- database result row as a :class:`.RowProxy` object.
+ database result row as a :class:`.Row` object.
E.g.::
@@ -307,7 +307,7 @@ first()
(<class '__main__.MyClass'>, (1, 2), None)
:param class: mapped class (must be a positional argument)
- :param row: :class:`.RowProxy` row returned by a :class:`.ResultProxy`
+ :param row: :class:`.Row` row returned by a :class:`.ResultProxy`
(must be given as a keyword arg)
:param identity_token: optional identity token