On Jun 8, 2013, at 1:33 AM, Greg Yang <sorcerero...@gmail.com> wrote:
> if __name__ == '__main__': > engine = create_engine('sqlite:///:memory:') > Session = sessionmaker(engine) > session = Session() > Base.metadata.create_all(engine) > > b1 = B() > b2 = B() > b3 = B() > > b1.a_color = 'blue' > session.add_all([b1, b2, b3]) > > q = session.query(B).filter(B.a_color == None).all() > p = session.query(B).filter(B.a_color != None).all() > > assert q == [] > assert set(p) == set([b1, b2, b3]) > > I find it surprising that, when only b1 really has a color string through > B.a_color, filtering for B.a_color == None doesn't return b2 and b3, and > filtering for B.a_color != None returns b2 and b3 at all. The latter is > especially unintuitive. The scalar comparison case was only rudimentally implemented. Along these lines, the case of query(B).filter(B.a_color != 'blue') also needed to be covered. Keeping in mind that in SQL, "x != 'somevalue'" does *not* return rows where "x IS NULL", this will now return those B's for which an A with non-NULL a_color is present but not equal to 'blue'. While the results are pretty wrong especially in the != None case, this seems strongly like an 0.9 only change, as it is very possible that applications are relying upon the current behavior. Particularly the "x == None" case not returning records for which an association row is not present could break an application that isn't prepared for those rows. The "x != 'somevalue'" case behaves very differently as well, no longer returning rows for which the association is missing. An illustration of all these cases contrasted can be seen in http://www.sqlalchemy.org/trac/ticket/2751. The changes are committed in r20d1e9c3fa8ccc992079. > > On a similar note, is there a way to get a_re.has() or equivalent through > only a_color? This can be important when a_re is supposed to be a private > variable, and only the string a_color is exposed. I originally thought that > != None would do the trick but that doesn't work, as I've shown here. this is like a "special operation" so I also added support for an empty call to B.a_color.has(). If you put criterion in there, it raises, because while you can do that, it doesn't really make any sense. The difference between B.a_color.has() and B.a_color != None is that the former will return you rows for which an A exists, regardless of whether or not A.color is NULL. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy?hl=en. For more options, visit https://groups.google.com/groups/opt_out.