orm load when col is missing fails to report correct exception

Issue #3658 resolved
Mike Bayer repo owner created an issue

1.0 regression, works in 0.9:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)
    x = Column(Integer)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

s = Session(e)
s.query(A.id, A.x).from_statement("select 1").all()

in 0.9:

sqlalchemy.exc.NoSuchColumnError: "Could not locate column in row for column 'a.id'"

in 1.0:

 File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/loading.py", line 74, in instances
 for row in fetch]
TypeError: 'NoneType' object is not callable

Comments (2)

  1. Mike Bayer reporter
    • reworked the way the "select_wraps_for" expression is handled within visit_select(); this attribute was added in the 1.0 series to accommodate the subquery wrapping behavior of SQL Server and Oracle while also working with positional column targeting and no longer relying upon "key fallback" in order to target columns in such a statement. The IBM DB2 third-party dialect also has this use case, but its implementation is using regular expressions to rewrite the textual SELECT only and does not make use of a "wrapped" select at this time. The logic no longer attempts to reconcile proxy set collections as this was not deterministic, and instead assumes that the select() and the wrapper select() match their columns postionally, at least for the column positions they have in common, so it is now very simple and safe. fixes #3657.
    • as a side effect of #3657 it was also revealed that the strategy of calling upon a ResultProxy._getter was not correctly calling into NoSuchColumnError when an expected column was not present, and instead returned None up to loading.instances() to produce NoneType failures; added a raiseerr argument to _getter() which is called when we aren't expecting None, fixes #3658.

    → <<cset 8ad968f33100>>

  2. Mike Bayer reporter
    • reworked the way the "select_wraps_for" expression is handled within visit_select(); this attribute was added in the 1.0 series to accommodate the subquery wrapping behavior of SQL Server and Oracle while also working with positional column targeting and no longer relying upon "key fallback" in order to target columns in such a statement. The IBM DB2 third-party dialect also has this use case, but its implementation is using regular expressions to rewrite the textual SELECT only and does not make use of a "wrapped" select at this time. The logic no longer attempts to reconcile proxy set collections as this was not deterministic, and instead assumes that the select() and the wrapper select() match their columns postionally, at least for the column positions they have in common, so it is now very simple and safe. fixes #3657.
    • as a side effect of #3657 it was also revealed that the strategy of calling upon a ResultProxy._getter was not correctly calling into NoSuchColumnError when an expected column was not present, and instead returned None up to loading.instances() to produce NoneType failures; added a raiseerr argument to _getter() which is called when we aren't expecting None, fixes #3658.

    (cherry picked from commit 8ad968f33100baeb3b13c7e0b724b6b79ab4277f)

    → <<cset cf818984ab52>>

  3. Log in to comment