On Jan 8, 2014, at 7:54 AM, limodou <[email protected]> wrote: > I think there are two things here: > > 1. Should None be converted to NULL when deal with "condition & None" or > "and_(condition, None)" > 2. How to combine multiple condition into one condition with and_ > > And I think the second question should be resolved by application itself, we > just need to obey some good guide, that's ok. > > But for the first question, the old style I think None's behavior just like > true(), but in 0.9.x, is not. So this makes the uncompatible process. Here is > a test for 0.9.1: > > >>> print and_('id=3', None) > id=3 AND NULL > >>> print and_('id=3', '') > id=3 > >>> print and_('id=3', true()) > id=3 > > So empty string is the same as true(), and why empty string can be treated as > true() but None is treated as NULL? Commonly, python will treat None, empty > string are false boolean value, but here sqlalchemy does do like that > obviously.
Here is a sample script using the code you gave. Your code is equally broken
in both 0.8 and 0.9, as if the list of conditions is empty, the same SELECT is
produced on both versions both of which are invalid with “WHERE NULL”:
from sqlalchemy.sql import select, column
def my_select(conditions):
cond = None
for c in conditions:
cond = c & cond
return select([column('x')]).where(cond)
print my_select([])
0.8.4:
SELECT x
WHERE NULL
0.9.1:
SELECT x
WHERE NULL
Therefore, your script cannot work in either 0.8 or 0.9, unless you fix it as
follows, in which case it works the same in both versions:
def my_select(conditions):
cond = conditions[0]
for c in conditions[1:]:
cond = c & cond
stmt = select([column(‘x’)])
if cond is not None:
stmt = stmt.where(cond)
return stmt
or you assume that “conditions” is non-empty, in which case, as I mentioned
earlier, do this:
def my_select(conditions):
cond = conditions[0]
for c in conditions[1:]:
cond = c & cond
return select([column('x')]).where(cond)
or preferably, just say and_(*conditions).
as for interpreting None as NULL, None has always been treated as NULL in a SQL
expression context - it is treated as NULL when used as a WHERE condition by
itself and it is treated as NULL when used in a comparison. 0.8 is
inconsistent that it is not treated as NULL when it happens to be part of an
AND:
from sqlalchemy.sql import select, column, literal
c = column('x')
print select([c]).where(c == 5) # 0.8 / 0.9: SELECT x WHERE x = :x_1
print select([c]).where(c == None) # 0.8 / 0.9: SELECT x WHERE x IS NULL
print select([c]).where("5”) # 0.8 / 0.9: SELECT x WHERE 5
print select([c]).where(None) # 0.8 / 0.9: SELECT x WHERE NULL
print select([c]).where((c == 5) & "5”) # 0.8 / 0.9: SELECT x WHERE x = :x_1
AND 5
print select([c]).where((c == 5) & None) # 0.8: SELECT x WHERE x = :x_1 #
0.9: SELECT x WHERE x = :x_1 AND NULL
The only thing that might be more appropriate than coercing where(None) and
where(x & None) into NULL would be raising an error - because in fact
where(<x>) and where(expr & <x>) already throws an exception if <x> is not a
SQL expression, string, or None/True/False (on both):
print select([c]).where(5) # 0.8 / 0.9 - raises exception
print select([c]).where(c & 5) # 0.8 / 0.9 - raises exception
None also doesn’t act like true() in 0.8:
print select([c]).where(true()) # 0.8: SELECT x WHERE true
print select([c]).where(None) # 0.8: SELECT x WHERE NULL
so overall, this change is mentioned in the “Migration Guide” exactly because
it is in fact a behavioral change. You can argue it should be listed under
“Core Behavioral Changes” instead of “Behavioral Improvements” and I wouldn’t
have much issue with that, it is just listed under “Improvements” because it
doesn’t change the behavior of code that’s written correctly in the first place.
>
> --
> I like python!
> UliPad <<The Python Editor>>: http://code.google.com/p/ulipad/
> UliWeb <<simple web framework>>: https://github.com/limodou/uliweb
> My Blog: http://my.oschina.net/limodou
>
> --
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.
signature.asc
Description: Message signed with OpenPGP using GPGMail
