-
-
Notifications
You must be signed in to change notification settings - Fork 64
fix: complete SQLAlchemy inheritance pattern support (STI, JTI, CTI) #611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: complete SQLAlchemy inheritance pattern support (STI, JTI, CTI) #611
Conversation
7badcce to
863a70b
Compare
|
Documentation preview will be available shortly at https://litestar-org.github.io/advanced-alchemy-docs-preview/611 |
8a01b76 to
acc57d0
Compare
- Modified CommonTableAttributes.__tablename__ to detect inheritance patterns - Changed from @declared_attr.directive (was causing issues) back to .directive - Returns None for STI children to use parent's table - Returns generated/explicit names for JTI/CTI patterns - Handles edge cases: mixins, abstract bases, multi-level hierarchies Fixes automatic table name generation for SQLAlchemy inheritance: - Single Table Inheritance (STI): Child uses parent table - Joined Table Inheritance (JTI): Child has own table with FK - Concrete Table Inheritance (CTI): Independent tables with concrete=True
The trailing underscore in `SyncServiceT_…` was being interpreted as an RST reference target, causing the doc build to fail with "Unknown target name: syncservicet".
6ef1f53 to
dc2b9d5
Compare
|
Would it be possible to add Polymorphism support for services and repositories? Currently, I've only been able to make Polymorphism work by creating a service for each subclass. Ideally it would work something like this: AllAlerts = with_polymorphic(Alert, (UnexpectedAlert, ExpectedAlert))
class AlertService(SQLAlchemyAsyncRepositoryService[AllAlerts]):
class Repo(SQLAlchemyAsyncRepository[AllAlerts]):
model_type = AllAlerts
repository_type = RepoAllAlerts is an AliasedClass that contains information about the Polymorphic relation. Just like SQLAlchemy, Advanced Alchemy typing would hint that it's methods return the abstract class. alert: Alert = await alert_service.create(data)But in practice, it really returns the full Polymorphic identity. I'm not sure how much additional work would be required, but this would be a great boon for services that provide many polymorphic identities. |
Thanks for the suggestion. I've opened up an enhancement request for this so that we can look at bringing it in an upcoming PR. |
Summary
This PR completes the implementation of SQLAlchemy inheritance pattern support in
CommonTableAttributes, enabling proper handling of Single Table Inheritance (STI), Joined Table Inheritance (JTI), and Concrete Table Inheritance (CTI).Changes
Core Implementation (advanced_alchemy/base.py)
Added
__init_subclass__hook (lines 209-277):polymorphic_onin their__mapper_args__cls.__tablename__ = Nonefor STI childrenpolymorphic_identity) and implicit (without) STI childrenEnhanced
@declared_attr.__tablename__()method (lines 281-386):Nonefor explicitly setNonevalues (set by__init_subclass__)Supported Patterns
✅ Single Table Inheritance (STI):
polymorphic_identityshare parent's tablepolymorphic_identity(with warning)✅ Joined Table Inheritance (JTI):
__tablename__create joined tables✅ Concrete Table Inheritance (CTI):
concrete=Truecreate independent tablesRelated Issues
Supersedes PR #600