negated_contains_or_equals inconsistently uses committed state, not state attr

Issue #3374 resolved
Mike Bayer repo owner created an issue
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)

class B(Base):
    __tablename__ = 'b'
    id = Column(Integer, primary_key=True)
    a_id = Column(ForeignKey('a.id'))
    a = relationship("A")

s = Session()


stmt = s.query(B).filter(B.a == A(id=7)).statement.compile()
print stmt
print stmt.params


stmt = s.query(B).filter(B.a != A(id=7)).statement.compile()
print stmt
print stmt.params

output:

#!

SELECT b.id, b.a_id 
FROM b 
WHERE :param_1 = b.a_id
{u'param_1': 7}

SELECT b.id, b.a_id 
FROM b 
WHERE b.a_id != :a_id_1 OR b.a_id IS NULL
{u'a_id_1': None}

because for the latter its pulling from committed state.

Comments (2)

  1. Mike Bayer reporter
    • Fixed more regressions caused by NEVER_SET; comparisons to transient objects with attributes unset would leak NEVER_SET, and negated_contains_or_equals would do so for any transient object as the comparison used only the committed value. Repaired the NEVER_SET cases, fixes #3371, and also made negated_contains_or_equals() use state_attr_by_column() just like a non-negated comparison, fixes #3374

    → <<cset a3af638e1a95>>

  2. Log in to comment