Conditions

Python provides interface for very complex operator overloading. The boolean operators cannot be overriden, that's why the sqlabstr interface uses the binary operators. Unfortunately the binary operators & (and) and | (or) have very high priority, you will have to be very careful about not forgetting correct parenthesis.

The condition can be appended to query using following instance methods: And(), Or(), AndNot(), OrNot(). Argument of the function is either a generic condition (described later) or, if the query represents only 1-table query, a pair column=value.

foo = db.foo()
foo.And(nick='andrew').AndNot(city='alabama')
foo.Or(nick='peter',city='New York')
# foo selects all 'andrew's who are not from Alabama, OR all 'peter's who are from 'New York'

Generic conditions

Generic conditions are specified using column names - attributes of the select instance. Apart from using the methods mentioned above (And(), Or(), AndNot(), OrNot()), you may use in-place operators &= and |= - they work exactly as functions And() and Or(). The left side of the condition should be a column name - use (foo.nick == 'andy') instead of ('andy' == foo.nick).
foo = db.foo()
foo &= (foo.nick != 'andy') & ((foo.age < 10) | (foo.age > 50)) # Line 1
foo |= (foo.nick == 'andy') & (foo.age > 50)                    # Line 2
# The result is (Line_1 OR Line_2)

Functions

SQL functions tend to have a pretty stupid syntax, which is not by default supported by this module. Support for these functions can be easily added, if you find it useful. That said, sqlabstr supports all normal multiparameter functions. They are accessible in the Database.f namespace and can be freely used in general conditions, Order() and DescOrder() functions and AddCol(). SQL functions are available in the db.f. namespace.
foo = db.foo()
foo &= db.f.surname(foo.name) == 'Bush' 
foo.AddCol(db.f.surname(foo.name), db.f.decode_id(foo.id))

Aggregate functions - grouping

SQL aggregate functions are available in db.a. namespace. If sqlabstr finds a column containing aggregate functions, it automatically groups the query by other columns (this is SQL requirement). If you want to group by a column, simply add it through AddCol(), and the column will be automatically added to GROUP BY clause. Sqlabstr supports the '*' and automatically fetches list of columns from database and builds column list in GROUP BY clause.
foo = db.foo()
foo.AddCol(db.a.average(foo.age), 
           foo.city)
## Computes average age of people in different cities

HAVING clause

Adding a HAVING clause is done using Having() method.
foo = self.db.foo('abc')
foo.AddCol(self.db.a.sum(foo.xyz) >> '	sum')
foo.Having(self.db.a.sum(foo.xyz) > 5)

Column renaming - AS

Should you wish give the columns a name, use the '>>' operator:
foo = db.foo()
foo.AddCol(db.a.average(foo.age) >> 'average_age',
	   foo.city >> 'city_name')
for row in foo:
    print row.city_name,':',row.average_age

Subqueries in WHERE clause

You can use subqueries in the WHERE clause as easily as using other condition. Special operator '<<' is provided for operator IN, other operators (ANY...) can be easily provided e.g. as db.f.any.
test = db.test('city',state='California')

foo = db.foo('nick','name')
foo &= foo.city << test
# 'Test' table would contain all cities in California, 
# foo query would contain all people who live in california.