summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/orm/__init__.py1
-rw-r--r--lib/sqlalchemy/orm/strategies.py36
-rw-r--r--lib/sqlalchemy/testing/fixtures.py5
3 files changed, 26 insertions, 16 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index a247b597b..8e9647840 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -44,6 +44,7 @@ from .interfaces import MapperProperty
from .interfaces import NOT_EXTENSION
from .interfaces import ONETOMANY
from .interfaces import PropComparator
+from .interfaces import UserDefinedOption
from .loading import merge_frozen_result
from .loading import merge_result
from .mapper import class_mapper
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index bf60c803d..069e5e667 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -1512,21 +1512,14 @@ class SubqueryLoader(PostLoader):
loadopt,
):
- if orig_query is context.query:
- options = new_options = orig_query._with_options
- else:
- # There's currently no test that exercises the necessity of
- # this step for subqueryload. Added in #6881, it is necessary for
- # selectinload, but its necessity for subqueryload is still
- # theoretical.
- options = orig_query._with_options
-
- new_options = [
- orig_opt._adjust_for_extra_criteria(context)
- if orig_opt._is_strategy_option
- else orig_opt
- for orig_opt in options
- ]
+ # note that because the subqueryload object
+ # does not re-use the cached query, instead always making
+ # use of the current invoked query, while we have two queries
+ # here (orig and context.query), they are both non-cached
+ # queries and we can transfer the options as is without
+ # adjusting for new criteria. Some work on #6881 / #6889
+ # brought this into question.
+ new_options = orig_query._with_options
if loadopt and loadopt._extra_criteria:
@@ -2933,9 +2926,12 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
if orig_query is context.query:
options = new_options = orig_query._with_options
+ user_defined_options = []
else:
options = orig_query._with_options
+ # propagate compile state options from the original query,
+ # updating their "extra_criteria" as necessary.
# note this will create a different cache key than
# "orig" options if extra_criteria is present, because the copy
# of extra_criteria will have different boundparam than that of
@@ -2946,6 +2942,14 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
if orig_opt._is_strategy_option
else orig_opt
for orig_opt in options
+ if orig_opt._is_compile_state or orig_opt._is_legacy_option
+ ]
+
+ # propagate user defined options from the current query
+ user_defined_options = [
+ opt
+ for opt in context.query._with_options
+ if not opt._is_compile_state and not opt._is_legacy_option
]
if loadopt and loadopt._extra_criteria:
@@ -2959,6 +2963,8 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
q = q.options(*new_options)._update_compile_options(
{"_current_path": effective_path}
)
+ if user_defined_options:
+ q = q.options(*user_defined_options)
if context.populate_existing:
q = q.execution_options(populate_existing=True)
diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py
index 30ada71cd..e6af0c546 100644
--- a/lib/sqlalchemy/testing/fixtures.py
+++ b/lib/sqlalchemy/testing/fixtures.py
@@ -548,7 +548,10 @@ _fixture_sessions = set()
def fixture_session(**kw):
kw.setdefault("autoflush", True)
kw.setdefault("expire_on_commit", True)
- sess = sa.orm.Session(config.db, **kw)
+
+ bind = kw.pop("bind", config.db)
+
+ sess = sa.orm.Session(bind, **kw)
_fixture_sessions.add(sess)
return sess