Three valued logic

Because of the way SQL handles NULL, there are some special operations available for expressing:

  • IS NULL
  • IS NOT NULL
  • IN
  • NOT IN

While it would be possible to use the IS NULL and IN operators with the negation operator (~), sometimes to get the correct semantics you will need to explicitly use IS NOT NULL and NOT IN.

The simplest way to use IS NULL and IN is to use the operator overloads:

  1. # Get all User objects whose last login is NULL.
  2. User.select().where(User.last_login >> None)
  3. # Get users whose username is in the given list.
  4. usernames = ['charlie', 'huey', 'mickey']
  5. User.select().where(User.username << usernames)

If you don’t like operator overloads, you can call the Field methods instead:

  1. # Get all User objects whose last login is NULL.
  2. User.select().where(User.last_login.is_null(True))
  3. # Get users whose username is in the given list.
  4. usernames = ['charlie', 'huey', 'mickey']
  5. User.select().where(User.username.in_(usernames))

To negate the above queries, you can use unary negation, but for the correct semantics you may need to use the special IS NOT and NOT IN operators:

  1. # Get all User objects whose last login is *NOT* NULL.
  2. User.select().where(User.last_login.is_null(False))
  3. # Using unary negation instead.
  4. User.select().where(~(User.last_login >> None))
  5. # Get users whose username is *NOT* in the given list.
  6. usernames = ['charlie', 'huey', 'mickey']
  7. User.select().where(User.username.not_in(usernames))
  8. # Using unary negation instead.
  9. usernames = ['charlie', 'huey', 'mickey']
  10. User.select().where(~(User.username << usernames))