compiler — SQLAlchemy 0.5.6 Documentation

# SQLAlchemy 0.5.6 Documentation

Search:
Version: 0.5.6 Last Updated: 09/13/2009 10:45:11

# 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)"