Repository navigation
Conversation
Implement is_derived_from() for TextualSelect so ORM relationship configuration can handle textual subqueries without raising NotImplementedError. Add a regression test covering a relationship join from a class mapped to a TextualSelect-derived subquery. Fixes: sqlalchemy#8326
Collaborator
|
Thanks! Issue #8326 is now marked code review in progress and no longer open for pull requests, so this pull request holds the review for it and another one won't land on top of your work. If this pull request is abandoned, a maintainer can put open for pull requests back on #8326 to reopen it to others. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This change adds a concrete
is_derived_from()implementation toTextualSelectso that aTextualSelect-derived subquery can participate in ORM relationship configuration without raisingNotImplementedError.The implementation intentionally returns
False. ATextualSelectis backed by opaque textual SQL rather than a SQLAlchemy-maintained selectable expression tree, so SQLAlchemy cannot reliably establish structuralFromClauseancestry from the text itself. ReturningFalseprovides the conservative derivation result expected by the selectable contract while allowing ORM relationship setup to continue.This addresses #8326.
Problem
A mapped class can use a subquery derived from
text(...).columns(...).subquery(...)as its selectable. When such a mapping also defines a relationship and that relationship is used while compiling a statement such as:ORM relationship configuration evaluates selectable ancestry through
is_derived_from().The subquery wrapper delegates that check to its underlying selectable. For a
TextualSelect, the inherited implementation ultimately raisesNotImplementedError, causing mapper / relationship configuration to fail during statement compilation.On current
main, the failure path is effectively:This is the current form of the issue originally reported in #8326.
Change
TextualSelectnow implements:This follows the behavior proposed in the issue discussion.
The result is deliberately conservative:
TextualSelectrepresents textual SQL and does not expose a structured selectable tree from which SQLAlchemy can safely infer table ancestry.Falsemeans that SQLAlchemy cannot establish that the textual selectable is structurally derived from the suppliedFromClause.The change therefore satisfies the selectable API contract needed by ORM relationship configuration without introducing unsupported SQL-text introspection.
Regression Test
A regression test was added to
test/orm/test_subquery_relations.py.The test:
Authortable;TextualSelectselectingid,title, andauthor_idfrom a textualpublicationquery;Bookimperatively to the resulting subquery;Book.authorrelationship using an explicitprimaryjoinwithforeign(...);select(Book).join(Book.author); andBefore the production change, this test fails with:
from the delegated
is_derived_from()call.After the change, the statement compiles successfully and the test passes.
Validation
The change was validated with the focused regression test and the complete related ORM test module.
Focused regression test:
Result:
Related ORM test module:
Result:
The original standalone reproduction was also rerun against the modified checkout:
It now compiles the expected join instead of raising
NotImplementedError.Formatting and lint checks:
Result: no lint errors.
Whitespace validation:
Result: clean.
Changelog
Added
doc/build/changelog/unreleased_21/8326.rstwithusecase, ormtags describing the supported ORM mapping use case.Scope
This PR is intentionally narrow. It implements the missing derivation contract needed for the ORM relationship configuration path described in #8326 and adds regression coverage for that behavior.
It does not attempt to infer foreign-key relationships from textual SQL or establish structural table lineage for arbitrary
TextualSelectcontents.Fixes: #8326