Yeah, implementing this a bit more, I'm fairly sure inheritance isn't what
I want for my use. I want the intelligent / easy linkage between the two
sets of tables - Sport and SourceSport, and Competition and
SourceCompetition - but none of the rest of what inheritance gives.
After pulling out the inheritance stuff, I think the closest I can get to
what I want is "source_competitions" set up like,
class SourceSport(_Sourcer):
source_competitions = relationship(
lambda: SourceCompetition,
primaryjoin=lambda: and_(
foreign(SourceSport.source_id) == SourceCompetition.source_id,
Competition.id == SourceCompetition.competition_id),
back_populates="source_sport",
uselist=True
)
Without a secondary/secondaryjoin. Without those, a "straight" query fails,
SourceSport.query
.join(SourceSport.source_competitions)
> no such column: competition.id [SQL: 'SELECT source_sport.sport_id AS
source_sport_sport_id, source_sport.source_sport_id AS
source_sport_source_sport_id, source_sport.source_id AS
source_sport_source_id \nFROM source_sport JOIN source_competition ON
source_sport.source_id = source_competition.source_id AND competition.id =
source_competition.competition_id
But if I join Competition,
SourceSport.query
.join(SourceSport.source_competitions)
.join(Competition)
SELECT source_sport.sport_id AS source_sport_sport_id,
source_sport.source_sport_id AS source_sport_source_sport_id,
source_sport.source_id AS source_sport_source_id
FROM source_sport JOIN source_competition ON source_sport.source_id =
source_competition.source_id AND competition.id =
source_competition.competition_id JOIN competition ON competition.id =
source_competition.competition_id
The query is perfect.
If I use anything from a table *not* joined, we hit the previous problem,
about that table being added to the FROM list,
SourceSport.query
.join(SourceSport.source_competitions)
.join(Competition)
.filter(
Source.key == 'main',
Sport.name == 'American Football',
Competition.key == 'NFL')
SELECT source_sport.sport_id AS source_sport_sport_id,
source_sport.source_sport_id AS source_sport_source_sport_id,
source_sport.source_id AS source_sport_source_id
FROM source, sport, source_sport JOIN source_competition ON
source_sport.source_id = source_competition.source_id AND competition.id =
source_competition.competition_id JOIN competition ON competition.id =
source_competition.competition_id
WHERE source."key" = ? AND sport.name = ? AND competition."key" = ?
INFO:sqlalchemy.engine.base.Engine:('main', 'American Football', 'NFL')
But if I ensure to remember to join any table I want to filter on, or any
table I want to have filled when it's returned from sqlalchemy, everything
works right,
SourceSport.query
.join(Sport)
.join(Source)
.join(SourceSport.source_competitions)
.join(Competition)
.options(
contains_eager(SourceSport.source_competitions)
.contains_eager(SourceCompetition.competition)
.contains_eager(Competition.sport),
contains_eager(SourceSport.source))
.filter(
Source.key == 'main',
Sport.name == 'American Football',
Competition.key == 'NFL')
SELECT sport.id AS sport_id, sport.name AS sport_name, competition.id AS
competition_id, competition."key" AS competition_key, competition.sport_id AS
competition_sport_id, source_competition.competition_id AS
source_competition_competition_id, source_competition.source_competition_id AS
source_competition_source_competition_id, source_competition.source_id AS
source_competition_source_id, source.id AS source_id, source."key" AS
source_key, source_sport.sport_id AS source_sport_sport_id,
source_sport.source_sport_id AS source_sport_source_sport_id,
source_sport.source_id AS source_sport_source_id
FROM source_sport JOIN sport ON sport.id = source_sport.sport_id JOIN source ON
source.id = source_sport.source_id JOIN source_competition ON
source_sport.source_id = source_competition.source_id AND competition.id =
source_competition.competition_id JOIN competition ON competition.id =
source_competition.competition_id
WHERE source."key" = ? AND sport.name = ? AND competition."key" = ?
INFO:sqlalchemy.engine.base.Engine:('main', 'American Football', 'NFL')
I *still* think that seems unnecessary given you've set all that connection
up in the relationship, but c'est la vie, I've spent way too much time on
this now.
On Tuesday, July 24, 2018 at 3:04:07 AM UTC+1, seaders wrote:
>
> Actually I see why that's happening now. Because of the inheritance (I'm
> assuming), sqlalchemy is creating a Sport record as a "parent" of every
> SourceSport created, and it's also creating a Competition record as a
> parent of every SourceCompetition created.
>
> Just looking back at my original post, in case I've caused confusion, my
> description of the class connection was wrong, for both Sport and
> Competition, and SourceSport and SourceCompetition respectively, they're
> 1-to-many relationships, not 1-to-1 as I'd indicated,
>
> Sport 1----* SourceSport
>
> Competition 1----* SourceCompetition
>
> The class structure was fine, but yeah Sport "has many" SourceSport's, and
> Competition has many SourceCompetition's. (Same as Source has many
> SourceSports, and also has many SourceCompetitions).
>
> Is this the default behaviour with this inheritance setup? I can't find
> any clear description of this in the documentation -
> http://docs.sqlalchemy.org/en/latest/orm/inheritance.html#joined-table-inheritance
>
> Obviously this is completely unwanted, and incorrect for my setup. The
> "parent" Sport for a SourceSport isn't a new item in the dB, it's the sport
> that's already created and referred to by SourceSport.sport.
>
--
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 post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.