Deferred column_property, subclassing and flush

Issue #3468 resolved
Former user created an issue

Hi! There is a quite specific test case for sqlalchemy 1.0.*. Deferred column_property if defined in a subclass, fails after flush.

The test passes in sqlalchemy 0.9.7 and fails in 1.0.0-1.0.6

    class A(self.Base):
        id = Column(Integer, primary_key=True)
    class B(A):
        id = Column(Integer, ForeignKey(A.id), primary_key=True)
        data = Column(String)
        expr = column_property(data+' '+data, deferred=True)

    b = B(id=2, data='aaa')
    db.add(b)
    db.flush()
    b.expr

Gives a following exception:

  File "sqlalchemy/orm/attributes.py", line 237, in __get__
    return self.impl.get(instance_state(instance), dict_)
  File "sqlalchemy/orm/attributes.py", line 592, in get
    "correctly" % key)
KeyError: "Deferred loader for attribute 'data' failed to populate correctly"

I have no idea what is going on, but the code of get function is a little bit strange for me:

def get(self, state, dict_, passive=PASSIVE_OFF):
    """..."""
    if self.key in dict_:
        return dict_[self.key]
    else:
        key = self.key
        if key not in state.committed_state or \
                state.committed_state[key] is NEVER_SET:

            ....

            elif value is ATTR_WAS_SET:
                try:
                    # XXX dict_[key] seems to be always not defined, because we have checked
                    #          self.key in dict_ before.
                    #          KeyError will always be raised
                    return dict_[key]
                except KeyError:
                    # TODO: no test coverage here.
                    raise KeyError(
                        "Deferred loader for attribute "
                        "%r failed to populate "
                        "correctly" % key)
...

Comments (7)

  1. Mike Bayer repo owner
    • Fixed 1.0 regression where a "deferred" attribute would not populate correctly if it were loaded within the "optimized inheritance load", which is a special SELECT emitted in the case of joined table inheritance used to populate expired or unloaded attributes against a joined table without loading the base table. This is related to the fact that SQLA 1.0 no longer guesses about loading deferred columns and must be directed explicitly. fixes #3468

    → <<cset 4d6f4ed184b9>>

  2. Log in to comment