Provides an API for creation of custom ClauseElements and compilers.
Usage involves the creation of one or more ClauseElement subclasses and one or more callables defining its compilation:
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import ColumnClause
class MyColumn(ColumnClause):
pass
@compiles(MyColumn)
def compile_mycolumn(element, compiler, **kw):
return "[%s]" % element.nameAbove, MyColumn extends ColumnClause, the base expression element for column objects. The compiles decorator registers itself with the MyColumn class so that it is invoked when the object is compiled to a string:
from sqlalchemy import select
s = select([MyColumn('x'), MyColumn('y')])
print str(s)Produces:
SELECT [x], [y]Compilers can also be made dialect-specific. The appropriate compiler will be invoked for the dialect in use:
from sqlalchemy.schema import DDLElement # this is a SQLA 0.6 construct
class AlterColumn(DDLElement):
def __init__(self, column, cmd):
self.column = column
self.cmd = cmd
@compiles(AlterColumn)
def visit_alter_column(element, compiler, **kw):
return "ALTER COLUMN %s ..." % element.column.name
@compiles(AlterColumn, 'postgres')
def visit_alter_column(element, compiler, **kw):
return "ALTER TABLE %s ALTER COLUMN %s ..." % (element.table.name, element.column.name)The second visit_alter_table will be invoked when any postgres dialect is used.
The compiler argument is the Compiled object in use. This object can be inspected for any information about the in-progress compilation, including compiler.dialect, compiler.statement etc. The SQLCompiler and DDLCompiler (DDLCompiler is 0.6. only) both include a process() method which can be used for compilation of embedded attributes:
class InsertFromSelect(ClauseElement):
def __init__(self, table, select):
self.table = table
self.select = select
@compiles(InsertFromSelect)
def visit_insert_from_select(element, compiler, **kw):
return "INSERT INTO %s (%s)" % (
compiler.process(element.table, asfrom=True),
compiler.process(element.select)
)
insert = InsertFromSelect(t1, select([t1]).where(t1.c.x>5))
print insertProduces:
"INSERT INTO mytable (SELECT mytable.x, mytable.y, mytable.z FROM mytable WHERE mytable.x > :x_1)"