Re: [Sqlalchemy-tickets] [sqlalchemy] #2734: __eq__ operator appears to not be working correctly fo
Brought to you by:
zzzeek
|
From: sqlalchemy <mi...@zz...> - 2013-05-29 18:25:28
|
#2734: __eq__ operator appears to not be working correctly for decorated types
-----------------------------------+------------------------------------
Reporter: mcclurem | Owner: zzzeek
Type: defect | Status: closed
Priority: medium | Milestone:
Component: declarative | Severity: no triage selected yet
Resolution: worksforme | Keywords: TypeDecorator
Progress State: completed/closed |
-----------------------------------+------------------------------------
Changes (by zzzeek):
* status: new => closed
* resolution: => worksforme
* status_field: awaiting triage => completed/closed
Comment:
unfortunately this is a special use case that requires additional logic,
because SQLAlchemy coerces any "obj == None" into "obj IS NULL" - if you
turn on SQL echoing you will see this, and it occurs before the type is
consulted. Because it's a lexical change to the statement, there's not
really any way to move this consultation to a later point.
So the `__eq__()` (and probably `__ne__()` also) here must be overridden
specifically:
{{{
#!python
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
class NullableString(TypeDecorator):
'''Turns None into the string "Null" and back in order to prevent
Null!=Null issues'''
impl = String
class comparator_factory(String.comparator_factory):
def __eq__(self, other):
if other is None:
return self.expr == "NONE"
else:
return String.comparator_factory.__eq__(self, other)
def process_bind_param(self, value, dialect):
return "NONE" if value is None else value
def process_result_value(self, value, dialect):
return None if value == "NONE" else value
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
value = Column(NullableString, nullable=False)
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
sess = Session(e)
sess.add_all([A(value='x'), A(value=None)])
sess.commit()
assert sess.execute("select id, value from a order by id").fetchall() ==
[(1, 'x'), (2, 'NONE')]
assert sess.query(A).filter(A.value == 'x').one().id == 1
assert sess.query(A).filter(A.value == None).one().id == 2
}}}
--
Ticket URL: <http://www.sqlalchemy.org/trac/ticket/2734#comment:1>
sqlalchemy <http://www.sqlalchemy.org/>
The Database Toolkit for Python
|