On Thu, Sep 14, 2023, at 7:36 AM, Cornelis Poppema wrote:
> Hi all,
>
> I am new to sqlalchemy, I think the idea of what I am trying to achieve is
> relatively simple, but I can't seem to figure out how to retrieve `.service`
> in the same query. I failed to find an example in the 2.0 documentation for
> exactly this.
>
> My attempts have been to simply chain a .selectinload after the
> .selectin_polymorphic, ie.:
>
> ```python
> .options(
> selectinload(StepModel.next_step, recursion_depth=-1),
> selectinload(StepModel.actionbases).selectin_polymorphic(
> [
> ServiceActionModel,
> ],
> )
> .selectinload(ServiceActionModel.service),
> raiseload("*"),
> )
> ```
>
> This gives the error:
>
> ```
> /usr/local/lib/python3.11/site-packages/sqlalchemy/orm/strategy_options.py:2442:
> in _raise_for_does_not_link
> raise sa_exc.ArgumentError(
> E sqlalchemy.exc.ArgumentError: ORM mapped entity or attribute
> "ServiceActionModel.service" does not link from relationship
> "StepModel.actionbases". Did you mean to use
> "StepModel.actionbases.of_type(ServiceActionModel)"?
> ```
Hi -
A few up front things, is it possible you can post these questions that have a
lot of code on github discussions? That's at
https://github.com/sqlalchemy/sqlalchemy/discussions . I'm sort of wondering
how new users are still arriving here at the mailing list, did you find this
list via the support page at https://www.sqlalchemy.org/support.html ? I
would want to change the verbiage there to please refer people to GH
discussions instead. Especially with these advanced inheritance eager
loading problems, which in the majority of cases end up being real bugs in
SQLAlchemy, as seems to be the case here (at least, there is an inconsistency
in the API that somehow needs to be documented, or something).
As for the question, first off this is really advanced usage and I've hardly
ever seen people using selectin_polymorphic(), much less deep within a chain of
loaders like this.
The correct form for this load would follow from how it's described at
https://docs.sqlalchemy.org/en/20/orm/queryguide/inheritance.html#combining-additional-loader-options-with-selectin-polymorphic-subclass-loads
, where the ORM allows the selectin_polymorphic(Target, [TargetSubclassA]) to
be a sibling to the appropriate relationship load,
selectinload(TargetSubclassA.elements). The example there places both of
these options comma-separated within select().options(). This is the
"inconsistent" part because I'm already surprised the ORM is allowing the
selectinload() to be present against TargetSubclassA when that's not one of the
primary entities in the select().
However in your case, you are coming off of a parent loader option already. So
following from this, the correct form based on a direct reading of those docs
would, *in theory*, be:
select().options(
selectinload(Parent.target).options(
selectin_polymorphic(Target, [TargetSubclassA]),
selectinload(TargetSubclassA.elements)
)
)
that is, you can build up sibling options from a parent loader option using
another call to .options().
however, this doesn't work; the validation of the loader chain unsurprisingly
notes that TargetSubclass is not linked from Parent.target, and they'd like you
to use of_type() instead. So I've made a bug for this here:
https://github.com/sqlalchemy/sqlalchemy/issues/10348 as something has to
change here, either the docs, or the usage pattern for selectin_polymorphic(),
or the error checks have to get a lot smarter to figure this out and let this
case pass, since it works fine the way you are expecting if I just have it skip
the error checking.
What you can do now is use with_polymorphic() instead that is more configurable
for this kind of loader chain:
TT = with_polymorphic(Target, [TargetSubclassA])
select().options(selectinload(Parent.target.of_type(TT).selectinload(TT.TargetSubclassA.elements)))
discussion can continue at the issue above or a new github discussion, thanks!
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable
Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/sqlalchemy/a99d9853-8936-455f-9439-bfe5f2e03faa%40app.fastmail.com.