assertion added for #3347 needs to be liberalized

Issue #3412 resolved
Mike Bayer repo owner created an issue

the assertion added in #3347 was there to trap cases where something unexpected was sent here; if the joins include some inner secondaries, then we might need to unwrap further:

# coding: utf-8

# Test case for SQLAlchemy bug,
# based on https://github.com/veekun/pokedex
# and https://github.com/veekun/spline-pokedex.

import sqlalchemy.ext.declarative
from sqlalchemy.orm import relationship, joinedload
from sqlalchemy.schema import Column, ForeignKey, Table
from sqlalchemy.types import Boolean, Integer, Unicode

TableBase = sqlalchemy.ext.declarative.declarative_base()
Session = sqlalchemy.orm.sessionmaker()


class Pokemon(TableBase):
    __tablename__ = 'pokemon'
    __singlename__ = 'pokemon'
    id = Column(Integer, primary_key=True, nullable=False)
    identifier = Column(Unicode(79), nullable=False)

    species_id = Column(Integer, ForeignKey('pokemon_species.id'))
    is_default = Column(Boolean)


class PokemonForm(TableBase):
    __tablename__ = 'pokemon_forms'
    __singlename__ = 'pokemon_form'
    id = Column(Integer, primary_key=True, nullable=False)

    pokemon_id = Column(Integer, ForeignKey('pokemon.id'))


class PokemonSpecies(TableBase):
    __tablename__ = 'pokemon_species'
    __singlename__ = 'pokemon_species'
    id = Column(Integer, primary_key=True, nullable=False)
    form_id = Column(ForeignKey('pokemon_forms.id'))

pokemon_types = Table(
    "pokemon_types",
    TableBase.metadata,
    Column("pokemon_id", Integer, ForeignKey('pokemon.id'), primary_key=True),
    Column("type_id", Integer, ForeignKey('types.id'), nullable=False)
)


class Type(TableBase):
    __tablename__ = 'types'
    __singlename__ = 'type'
    id = Column(Integer, primary_key=True)
    identifier = Column(Unicode(79))

    # pokemon_id = Column(ForeignKey("pokemon.id"))

Pokemon.types = relationship(Type,
                             secondary=pokemon_types,
                             innerjoin=True,
                             )

PokemonForm.pokemon = relationship(
    Pokemon,
    innerjoin=True)

PokemonSpecies.default_form = relationship(PokemonForm)


session = Session()

# PokemonSpecies -> (Pokemon) -> PokemonForm -> Pokemon -> (PokemonType) -> Type

q = session.query(PokemonSpecies) \
    .options(
        joinedload('default_form').
        joinedload('pokemon').joinedload('types'))
print(q)

Comments (1)

  1. Mike Bayer reporter
    • Liberalized an assertion that was added as part of 🎫3347 to protect against unknown conditions when splicing inner joins together within joined eager loads with innerjoin=True; if some of the joins use a "secondary" table, the assertion needs to unwrap further joins in order to pass. fixes #3412

    → <<cset 8ac2bec0292d>>

  2. Log in to comment