On Jan 8, 2014, at 7:54 AM, limodou <limo...@gmail.com> 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 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.
> For more options, visit https://groups.google.com/groups/opt_out.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to