SQLAlchemy 0.5.5 Documentation

Version: 0.5.5 Last Updated: 07/13/2009 15:02:35
API Reference | Index

compiler

Provides an API for creation of custom ClauseElements and compilers.

Synopsis

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.name

Above, 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 insert

Produces:

"INSERT INTO mytable (SELECT mytable.x, mytable.y, mytable.z FROM mytable WHERE mytable.x > :x_1)"
Previous: SqlSoup