summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/context.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-06-07 18:49:04 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-06-08 10:45:20 -0400
commit4e8577ca66d194661b1fed01c46a529655473b97 (patch)
tree9e90706a11071738dec18cdcdd8b462c739a8013 /lib/sqlalchemy/orm/context.py
parent94169108cdd4dace09b752a6af4f4404819b49a3 (diff)
downloadsqlalchemy-4e8577ca66d194661b1fed01c46a529655473b97.tar.gz
restore adapter logic in ORM loading
Fixed regression involving how the ORM would resolve a given mapped column to a result row, where under cases such as joined eager loading, a slightly more expensive "fallback" could take place to set up this resolution due to some logic that was removed since 1.3. The issue could also cause deprecation warnings involving column resolution to be emitted when using a 1.4 style query with joined eager loading. In order to ensure we don't look up columns by string name in the ORM, we've turned on future_result=True in all cases, which I thought was already the assumption here, but apparently not. That in turn led to the issue that Session autocommit relies on close_with_result=True, which is legacy result only. This was also hard to figure out. So a new exception is raised if one tries to use future_result=True along with close_with_result, and the Session now has an explicit path for "autocommit" that sets these flags to their legacy values. This does leave the possibility of some of these fallback cases emitting warnings for users using session in autocommit along with joined inheritance and column properties, as this patch identifies that joined inheritance + column properties produce the fallback logic when looking up in the result via the adapted column, which in those tests is actually a Label object that doesn't adapt nicely. Fixes: #6596 Change-Id: I107a47e873ae05ab50853bb00a9ea0e1a88d5aee
Diffstat (limited to 'lib/sqlalchemy/orm/context.py')
-rw-r--r--lib/sqlalchemy/orm/context.py24
1 files changed, 14 insertions, 10 deletions
diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py
index d60758ffc..e4448f953 100644
--- a/lib/sqlalchemy/orm/context.py
+++ b/lib/sqlalchemy/orm/context.py
@@ -127,8 +127,8 @@ class QueryContext(object):
)
-_result_disable_adapt_to_context = util.immutabledict(
- {"_result_disable_adapt_to_context": True}
+_orm_load_exec_options = util.immutabledict(
+ {"_result_disable_adapt_to_context": True, "future_result": True}
)
@@ -239,16 +239,20 @@ class ORMCompileState(CompileState):
statement._execution_options,
)
- # add _result_disable_adapt_to_context=True to execution options.
- # this will disable the ResultSetMetadata._adapt_to_context()
- # step which we don't need, as we have result processors cached
- # against the original SELECT statement before caching.
+ # default execution options for ORM results:
+ # 1. _result_disable_adapt_to_context=True
+ # this will disable the ResultSetMetadata._adapt_to_context()
+ # step which we don't need, as we have result processors cached
+ # against the original SELECT statement before caching.
+ # 2. future_result=True. The ORM should **never** resolve columns
+ # in a result set based on names, only on Column objects that
+ # are correctly adapted to the context. W the legacy result
+ # it will still attempt name-based resolution and also emit a
+ # warning.
if not execution_options:
- execution_options = _result_disable_adapt_to_context
+ execution_options = _orm_load_exec_options
else:
- execution_options = execution_options.union(
- _result_disable_adapt_to_context
- )
+ execution_options = execution_options.union(_orm_load_exec_options)
if "yield_per" in execution_options or load_options._yield_per:
execution_options = execution_options.union(