alembic documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py the...

49
Alembic Documentation Release 0.2.2 Mike Bayer January 17, 2014

Upload: others

Post on 19-Jul-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic DocumentationRelease 0.2.2

Mike Bayer

January 17, 2014

Page 2: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of
Page 3: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Contents

i

Page 4: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

ii

Page 5: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

Alembic is a lightweight database migration tool for usage with the SQLAlchemy Database Toolkit for Python.

Contents 1

Page 6: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

2 Contents

Page 7: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

CHAPTER 1

Front Matter

Information about the Alembic project.

1.1 Project Homepage

Alembic is hosted on Bitbucket - the lead project page is at https://bitbucket.org/zzzeek/alembic. Source code istracked here using Mercurial.

Releases and project status are available on Pypi at http://pypi.python.org/pypi/alembic.

The most recent published version of this documentation should be at http://alembic.readthedocs.org/.

1.2 Project Status

Note that Alembic is still in alpha status. Users should take care to report bugs and missing features (seeBugs) on an as-needed basis. It should be expected that the development version may be required forproper implementation of recently repaired issues in between releases; the latest tip is always available athttps://bitbucket.org/zzzeek/alembic/get/tip.tar.gz.

1.3 Installation

Install released versions of Alembic from the Python package index with pip or a similar tool:

pip install alembic

Installation via source distribution is via the setup.py script:

python setup.py install

The install will add the alembic command to the environment. All operations with Alembic then proceed throughthe usage of this command.

1.3.1 Dependencies

Alembic’s install process will ensure that SQLAlchemy is installed, in addition to other dependencies. Alembic willwork with SQLAlchemy as of version 0.6, though with a limited featureset. The latest version of SQLAlchemy withinthe 0.7 series is strongly recommended.

3

Page 8: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

1.4 Upgrading from Alembic 0.1 to 0.2

Alembic 0.2 has some reorganizations and features that might impact an existing 0.1 installation. These include:

• The naming convention for migration files is now customizable, and defaults to the scheme “%(rev)s_%(slug)s”,where “slug” is based on the message added to the script. When Alembic reads one of these files, it looks ata new variable named revision inside of the script to get at the revision identifier. Scripts that use the newnaming convention will need to render this revision identifier inside the script, so the script.py.makofile within an existing alembic environment needs to have both revision and down_revision specified:

# revision identifiers, used by Alembic.revision = ${repr(up_revision)}down_revision = ${repr(down_revision)}

Existing scripts that use the 0.1 naming convention don’t have to be changed, unless you are renaming them.Alembic will fall back to pulling in the version identifier from the filename if revision isn’t present, as longas the filename uses the old naming convention.

• The alembic.op and alembic.context modules are now generated as a collection of proxy functions,which when used refer to an object instance installed when migrations run. alembic.op refers to an instanceof the Operations object, and alembic.context refers to an instance of the EnvironmentContextobject. Most existing setups should be able to run with no changes, as the functions are established at moduleload time and remain fully importable.

1.5 Community

Alembic is developed by Mike Bayer, and is loosely associated with the SQLAlchemy and Pylons projects.

User issues, discussion of potential bugs and features should be posted to the Alembic Google Group at sqlalchemy-alembic.

1.6 Bugs

Bugs and feature enhancements to Alembic should be reported on the Bitbucket issue tracker.

4 Chapter 1. Front Matter

Page 9: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

CHAPTER 2

Tutorial

Alembic provides for the creation, management, and invocation of change management scripts for a relationaldatabase, using SQLAlchemy as the underlying engine. This tutorial will provide a full introduction to the theoryand usage of this tool.

To begin, make sure Alembic is installed as described at Installation.

2.1 The Migration Environment

Usage of Alembic starts with creation of the Migration Environment. This is a directory of scripts that is specific to aparticular application. The migration environment is created just once, and is then maintained along with the applica-tion’s source code itself. The environment is created using the init command of Alembic, and is then customizableto suit the specific needs of the application.

The structure of this environment, including some generated migration scripts, looks like:

yourproject/alembic/

env.pyREADMEscript.py.makoversions/

3512b954651e_add_account.py2b1ae634e5cd_add_order_id.py3adcc9a56557_rename_username_field.py

The directory includes these directories/files:

• yourproject - this is the root of your application’s source code, or some directory within it.

• alembic - this directory lives within your application’s source tree and is the home of the migration environ-ment. It can be named anything, and a project that uses multiple databases may even have more than one.

• env.py - This is a Python script that is run whenever the alembic migration tool is invoked. At the very least,it contains instructions to configure and generate a SQLAlchemy engine, procure a connection from that enginealong with a transaction, and to then invoke the migration engine, using the connection as a source of databaseconnectivity.

The env.py script is part of the generated environment so that the way migrations run is entirely customizable.The exact specifics of how to connect are here, as well as the specifics of how the migration enviroment areinvoked. The script can be modified so that multiple engines can be operated upon, custom arguments can bepassed into the migration environment, application-specific libraries and models can be loaded in and madeavailable.

5

Page 10: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

Alembic includes a set of initialization templates which feature different varieties of env.py for different usecases.

• README - included with the various enviromnent templates, should have something informative.

• script.py.mako - This is a Mako template file which is used to generate new migration scripts. Whatever ishere is used to generate new files within versions/. This is scriptable so that the structure of each migrationfile can be controlled, including standard imports to be within each, as well as changes to the structure of theupgrade() and downgrade() functions. For example, the multidb environment allows for multiplefunctions to be generated using a naming scheme upgrade_engine1(), upgrade_engine2().

• versions/ - This directory holds the individual version scripts. Users of other migration tools may noticethat the files here don’t use ascending integers, and instead use a partial GUID approach. In Alembic, theordering of version scripts is relative to directives within the scripts themselves, and it is theoretically possibleto “splice” version files in between others, allowing migration sequences from different branches to be merged,albeit carefully by hand.

2.2 Creating an Environment

With a basic understanding of what the environment is, we can create one using alembic init. This will create anenvironment using the “generic” template:

$ cd yourproject$ alembic init alembic

Where above, the init command was called to generate a migrations directory called alembic:

Creating directory /path/to/yourproject/alembic...doneCreating directory /path/to/yourproject/alembic/versions...doneGenerating /path/to/yourproject/alembic.ini...doneGenerating /path/to/yourproject/alembic/env.py...doneGenerating /path/to/yourproject/alembic/README...doneGenerating /path/to/yourproject/alembic/script.py.mako...donePlease edit configuration/connection/logging settings in’/path/to/yourproject/alembic.ini’ before proceeding.

Alembic also includes other environment templates. These can be listed out using the list_templates command:

$ alembic list_templatesAvailable templates:

generic - Generic single-database configuration.multidb - Rudimentary multi-database configuration.pylons - Configuration that reads from a Pylons project environment.

Templates are used via the ’init’ command, e.g.:

alembic init --template pylons ./scripts

2.3 Editing the .ini File

Alembic placed a file alembic.ini into the current directory. This is a file that the alembic script looks for wheninvoked. This file can be anywhere, either in the same directory from which the alembic script will normally beinvoked, or if in a different directory, can be specified by using the --config option to the alembic runner.

6 Chapter 2. Tutorial

Page 11: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

The file generated with the “generic” configuration looks like:

# A generic, single database configuration.

[alembic]# path to migration scriptsscript_location = alembic

# template used to generate migration files# file_template = %%(rev)s_%%(slug)s

sqlalchemy.url = driver://user:pass@localhost/dbname

# Logging configuration[loggers]keys = root,sqlalchemy,alembic

[handlers]keys = console

[formatters]keys = generic

[logger_root]level = WARNhandlers = consolequalname =

[logger_sqlalchemy]level = WARNhandlers =qualname = sqlalchemy.engine

[logger_alembic]level = INFOhandlers =qualname = alembic

[handler_console]class = StreamHandlerargs = (sys.stderr,)level = NOTSETformatter = generic

[formatter_generic]format = %(levelname)-5.5s [%(name)s] %(message)sdatefmt = %H:%M:%S

The file is read using Python’s ConfigParser.SafeConfigParser object. The %(here)s variable is pro-vided as a substitution variable, which can be used to produce absolute pathnames to directories and files, as we doabove with the path to the Alembic script location.

This file contains the following features:

• [alembic] - this is the section read by Alembic to determine configuration. Alembic itself does not directlyread any other areas of the file.

• script_location - this is the location of the Alembic environment. It is normally specified as a filesystemlocation, either relative or absolute. If the location is a relative path, it’s interpreted as relative to the currentdirectory.

2.3. Editing the .ini File 7

Page 12: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

This is the only key required by Alembic in all cases. The generation of the .ini file by the command alembicinit alembic automatically placed the directory name alembic here. The special variable %(here)scan also be used, as in %(here)s/alembic.

For support of applications that package themselves into .egg files, the value can also be specified as a packageresource, in which case resource_filename() is used to find the file (new in 0.2.2). Any non-absoluteURI which contains colons is interpreted here as a resource name, rather than a straight filename.

• file_template - this is the naming scheme used to generate new migration files. The value present is thedefault, so is commented out. The two tokens available are %%(rev)s and %%(slug)s, where %%(slug)sis a truncated string derived from the revision message.

• sqlalchemy.url - A URL to connect to the database via SQLAlchemy. This key is in fact only referencedwithin the env.py file that is specific to the “generic” configuration; a file that can be customized by thedeveloper. A multiple database configuration may respond to multiple keys here, or may reference other sectionsof the file.

• [loggers], [handlers], [formatters], [logger_*], [handler_*], [formatter_*] - thesesections are all part of Python’s standard logging configuration, the mechanics of which are documented atConfiguration File Format. As is the case with the database connection, these directives are used directly as theresult of the logging.config.fileConfig() call present in the env.py script, which you’re free tomodify.

For starting up with just a single database and the generic configuration, setting up the SQLAlchemy URL is all that’sneeded:

sqlalchemy.url = postgresql://scott:tiger@localhost/test

2.4 Create a Migration Script

With the environment in place we can create a new revision, using alembic revision:

$ alembic revision -m "create account table"Generating /path/to/yourproject/alembic/versions/1975ea83b712_create_account_table.py...done

A new file 1975ea83b712_create_account_table.py is generated. Looking inside the file:

"""create account table

Revision ID: 1975ea83b712Revises: NoneCreate Date: 2011-11-08 11:40:27.089406

"""

# revision identifiers, used by Alembic.revision = ’1975ea83b712’down_revision = None

from alembic import opimport sqlalchemy as sa

def upgrade():pass

def downgrade():pass

8 Chapter 2. Tutorial

Page 13: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

The file contains some header information, identifiers for the current revision and a “downgrade” revision, an importof basic Alembic directives, and empty upgrade() and downgrade() functions. Our job here is to populate theupgrade() and downgrade() functions with directives that will apply a set of changes to our database. Typically,upgrade() is required while downgrade() is only needed if down-revision capability is desired, though it’sprobably a good idea.

Another thing to notice is the down_revision variable. This is how Alembic knows the correct order in which toapply migrations. When we create the next revision, the new file’s down_revision identifier would point to thisone:

# revision identifiers, used by Alembic.revision = ’ae1027a6acf’down_revision = ’1975ea83b712’

Every time Alembic runs an operation against the versions/ directory, it reads all the files in, and composes a listbased on how the down_revision identifiers link together, with the down_revision of None representing thefirst file. In theory, if a migration environment had thousands of migrations, this could begin to add some latency tostartup, but in practice a project should probably prune old migrations anyway (see the section Building an Up to DateDatabase from Scratch for a description on how to do this, while maintaining the ability to build the current databasefully).

We can then add some directives to our script, suppose adding a new table account:

def upgrade():op.create_table(

’account’,sa.Column(’id’, sa.Integer, primary_key=True),sa.Column(’name’, sa.String(50), nullable=False),sa.Column(’description’, sa.Unicode(200)),

)

def downgrade():op.drop_table(’account’)

create_table() and drop_table() are Alembic directives. Alembic provides all the basic database migrationoperations via these directives, which are designed to be as simple and minimalistic as possible; there’s no relianceupon existing table metadata for most of these directives. They draw upon a global “context” that indicates how toget at a database connection (if any; migrations can dump SQL/DDL directives to files as well) in order to invoke thecommand. This global context is set up, like everything else, in the env.py script.

An overview of all Alembic directives is at Operation Reference.

2.5 Running our First Migration

We now want to run our migration. Assuming our database is totally clean, it’s as yet unversioned. The alembicupgrade command will run upgrade operations, proceeding from the current database revision, in this exampleNone, to the given target revision. We can specify 1975ea83b712 as the revision we’d like to upgrade to, but it’seasier in most cases just to tell it “the most recent”, in this case head:

$ alembic upgrade headINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.INFO [alembic.context] Running upgrade None -> 1975ea83b712

2.5. Running our First Migration 9

Page 14: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

Wow that rocked ! Note that the information we see on the screen is the result of the logging configuration set up inalembic.ini - logging the alembic stream to the console (standard error, specifically).

The process which occurred here included that Alembic first checked if the database had a table calledalembic_version, and if not, created it. It looks in this table for the current version, if any, and then calcu-lates the path from this version to the version requested, in this case head, which is known to be 1975ea83b712.It then invokes the upgrade() method in each file to get to the target revision.

2.6 Running our Second Migration

Let’s do another one so we have some things to play with. We again create a revision file:

$ alembic revision -m "Add a column"Generating /path/to/yourapp/alembic/versions/ae1027a6acf.py_add_a_column.py...done

Let’s edit this file and add a new column to the account table:

"""Add a column

Revision ID: ae1027a6acfRevises: 1975ea83b712Create Date: 2011-11-08 12:37:36.714947

"""

# revision identifiers, used by Alembic.revision = ’ae1027a6acf’down_revision = ’1975ea83b712’

from alembic import opimport sqlalchemy as sa

def upgrade():op.add_column(’account’, sa.Column(’last_transaction_date’, sa.DateTime))

def downgrade():op.drop_column(’account’, ’last_transaction_date’)

Running again to head:

$ alembic upgrade headINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.INFO [alembic.context] Running upgrade 1975ea83b712 -> ae1027a6acf

We’ve now added the last_transaction_date column to the database.

2.7 Getting Information

With a few revisions present we can get some information about the state of things.

First we can view the current revision:

10 Chapter 2. Tutorial

Page 15: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

$ alembic currentINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.Current revision for postgresql://scott:XXXXX@localhost/test: 1975ea83b712 -> ae1027a6acf (head), Add a column

We can also view history:

$ alembic history

1975ea83b712 -> ae1027a6acf (head), Add a columnNone -> 1975ea83b712, empty message

We can also identify specific migrations using just enough characters to uniquely identify them. If we wanted toupgrade directly to ae1027a6acf we could say:

$ alembic upgrade ae1

Alembic will stop and let you know if more than one version starts with that prefix.

2.8 Downgrading

We can illustrate a downgrade back to nothing, by calling alembic downgrade back to the beginning, which inAlembic is called base:

$ alembic downgrade baseINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.INFO [alembic.context] Running downgrade ae1027a6acf -> 1975ea83b712INFO [alembic.context] Running downgrade 1975ea83b712 -> None

Back to nothing - and up again:

$ alembic upgrade headINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.INFO [alembic.context] Running upgrade None -> 1975ea83b712INFO [alembic.context] Running upgrade 1975ea83b712 -> ae1027a6acf

2.9 Auto Generating Migrations

Alembic can view the status of the database and compare against the table metadata in the application, generating the“obvious” migrations based on a comparison. This is achieved using the --autogenerate option to the alembicrevision command, which places so-called candidate migrations into our new migrations file. We review andmodify these by hand as needed, then proceed normally.

To use autogenerate, we first need to modify our env.py so that it gets access to a table metadata object that containsthe target. Suppose our application has a declarative base in myapp.mymodel. This base contains a MetaDataobject which contains Table objects defining our database. We make sure this is loaded in env.py and then passedto EnvironmentContext.configure() via the target_metadata argument. The env.py sample scriptalready has a variable declaration near the top for our convenience, where we replace None with our MetaData.Starting with:

# add your model’s MetaData object here# for ’autogenerate’ support

2.8. Downgrading 11

Page 16: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

# from myapp import mymodel# target_metadata = mymodel.Base.metadatatarget_metadata = None

we change to:

from myapp.mymodel import Basetarget_metadata = Base.metadata

If we look later in the script, down in run_migrations_online(), we can see the directive passed toEnvironmentContext.configure():

def run_migrations_online():engine = engine_from_config(

config.get_section(config.config_ini_section), prefix=’sqlalchemy.’)

connection = engine.connect()context.configure(

connection=connection,target_metadata=target_metadata)

trans = connection.begin()try:

context.run_migrations()trans.commit()

except:trans.rollback()raise

We can then use the alembic revision command in conjunction with the --autogenerate option. Supposeour MetaData contained a definition for the account table, and the database did not. We’d get output like:

$ alembic revision --autogenerate -m "Added account table"INFO [alembic.context] Detected added table ’account’Generating /Users/classic/Desktop/tmp/alembic/versions/27c6a30d7c24.py...done

We can then view our file 27c6a30d7c24.py and see that a rudimentary migration is already present:

"""empty message

Revision ID: 27c6a30d7c24Revises: NoneCreate Date: 2011-11-08 11:40:27.089406

"""

# revision identifiers, used by Alembic.revision = ’27c6a30d7c24’down_revision = None

from alembic import opimport sqlalchemy as sa

def upgrade():### commands auto generated by Alembic - please adjust! ###op.create_table(’account’,sa.Column(’id’, sa.Integer()),

12 Chapter 2. Tutorial

Page 17: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

sa.Column(’name’, sa.String(length=50), nullable=False),sa.Column(’description’, sa.VARCHAR(200)),sa.Column(’last_transaction_date’, sa.DateTime()),sa.PrimaryKeyConstraint(’id’))### end Alembic commands ###

def downgrade():### commands auto generated by Alembic - please adjust! ###op.drop_table("account")### end Alembic commands ###

The migration hasn’t actually run yet, of course. We do that via the usual upgrade command. We should also gointo our migration file and alter it as needed, including adjustments to the directives as well as the addition of otherdirectives which these may be dependent on - specifically data changes in between creates/alters/drops.

Autogenerate will by default detect:

• Table additions, removals.

• Column additions, removals.

• Change of nullable status on columns.

Autogenerate can optionally detect:

• Change of column type. This will occur if you set compare_type=True onEnvironmentContext.configure(). The feature works well in most cases, but is off by defaultso that it can be tested on the target schema first. It can also be customized by passing a callable here; see thefunction’s documentation for details.

• Change of server default. This will occur if you set compare_server_default=True onEnvironmentContext.configure(). This feature works well for simple cases but cannot always pro-duce accurate results. The Postgresql backend will actually invoke the “detected” and “metadata” values againstthe database to determine equivalence. The feature is off by default so that it can be tested on the target schemafirst. Like type comparison, it can also be customized by passing a callable; see the function’s documentationfor details.

Autogenerate can not detect:

• Changes of table name. These will come out as an add/drop of two different tables, and should be hand-editedinto a name change instead.

• Changes of column name. Like table name changes, these are detected as a column add/drop pair, which is notat all the same as a name change.

Autogenerate can’t currently, but will eventually detect:

• Free-standing constraint additions, removals, like CHECK, UNIQUE, FOREIGN KEY - these aren’t yet imple-mented. Right now you’ll get constraints within new tables, PK and FK constraints for the “downgrade” to a pre-viously existing table, and the CHECK constraints generated with a SQLAlchemy “schema” types Boolean,Enum.

• Index additions, removals - not yet implemented.

• Sequence additions, removals - not yet implemented.

2.9. Auto Generating Migrations 13

Page 18: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

2.10 Generating SQL Scripts (a.k.a. “Offline Mode”)

A major capability of Alembic is to generate migrations as SQL scripts, instead of running them against the database- this is also referred to as offline mode. This is a critical feature when working in large organizations where accessto DDL is restricted, and SQL scripts must be handed off to DBAs. Alembic makes this easy via the --sql optionpassed to any upgrade or downgrade command. We can, for example, generate a script that revises up to revae1027a6acf:

$ alembic upgrade ae1027a6acf --sqlINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.BEGIN;

CREATE TABLE alembic_version (version_num VARCHAR(32) NOT NULL

);

INFO [alembic.context] Running upgrade None -> 1975ea83b712CREATE TABLE account (

id SERIAL NOT NULL,name VARCHAR(50) NOT NULL,description VARCHAR(200),PRIMARY KEY (id)

);

INFO [alembic.context] Running upgrade 1975ea83b712 -> ae1027a6acfALTER TABLE account ADD COLUMN last_transaction_date TIMESTAMP WITHOUT TIME ZONE;

INSERT INTO alembic_version (version_num) VALUES (’ae1027a6acf’);

COMMIT;

While the logging configuration dumped to standard error, the actual script was dumped to standard output - so in theabsence of further configuration (described later in this section), we’d at first be using output redirection to generate ascript:

$ alembic upgrade ae1027a6acf --sql > migration.sql

2.10.1 Getting the Start Version

Notice that our migration script started at the base - this is the default when using offline mode, as no databaseconnection is present and there’s no alembic_version table to read from.

One way to provide a starting version in offline mode is to provide a range to the command line. This is accomplishedby providing the “version” in start:end syntax:

$ alembic upgrade 1975ea83b712:ae1027a6acf --sql > migration.sql

The start:end syntax is only allowed in offline mode; in “online” mode, the alembic_version table is alwaysused to get at the current version.

It’s also possible to have the env.py script retrieve the “last” version from the local environment, such as from alocal file. A scheme like this would basically treat a local file in the same way alembic_version works:

if context.is_offline_mode():version_file = os.path.join(os.path.dirname(config.config_file_name), "version.txt")if os.path.exists(version_file):

14 Chapter 2. Tutorial

Page 19: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

current_version = open(version_file).read()else:

current_version = Nonecontext.configure(dialect_name=engine.name, starting_version=current_version)context.run_migrations()end_version = context.get_revision_argument()if end_version and end_version != current_version:

open(version_file, ’w’).write(end_version)

2.10.2 Writing Migration Scripts to Support Script Generation

The challenge of SQL script generation is that the scripts we generate can’t rely upon any client/server database access.This means a migration script that pulls some rows into memory via a SELECT statement will not work in --sqlmode. It’s also important that the Alembic directives, all of which are designed specifically to work in both “liveexecution” as well as “offline SQL generation” mode, are used.

2.10.3 Customizing the Environment

Users of the --sql option are encouraged to hack their env.py files to suit their needs. Theenv.py script as provided is broken into two sections: run_migrations_online() andrun_migrations_offline(). Which function is run is determined at the bottom of the script by read-ing EnvironmentContext.is_offline_mode(), which basically determines if the --sql flag wasenabled.

For example, a multiple database configuration may want to run through each database and set the output of themigrations to different named files - the EnvironmentContext.configure() function accepts a parameteroutput_buffer for this purpose. Below we illustrate this within the run_migrations_offline() function:

from alembic import contextimport myappimport sys

db_1 = myapp.db_1db_2 = myapp.db_2

def run_migrations_offline():"""Run migrations *without* a SQL connection."""

for name, engine, file_ in [("db1", db_1, "db1.sql"),("db2", db_2, "db2.sql"),

]:context.configure(

url=engine.url,transactional_ddl=False,output_buffer=open(file_, ’w’))

context.execute("-- running migrations for ’%s’" % name)context.run_migrations(name=name)sys.stderr.write("Wrote file ’%s’" % file_)

def run_migrations_online():"""Run migrations *with* a SQL connection."""

for name, engine in [("db1", db_1),

2.10. Generating SQL Scripts (a.k.a. “Offline Mode”) 15

Page 20: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

("db2", db_2),]:

connection = engine.connect()context.configure(connection=connection)try:

context.run_migrations(name=name)session.commit()

except:session.rollback()raise

if context.is_offline_mode():run_migrations_offline()

else:run_migrations_online()

2.11 Working with Branches

A branch describes when a source tree is broken up into two versions representing two independent sets of changes.The challenge of a branch is to merge the branches into a single series of changes. Alembic’s GUID-based versionnumber scheme allows branches to be reconciled.

Consider if we merged into our source repository another branch which contained a revision for another table calledshopping_cart. This revision was made against our first Alembic revision, the one that generated account.After loading the second source tree in, a new file 27c6a30d7c24.py exists within our versions directory. Bothit, as well as ae1027a6acf.py, reference 1975ea83b712 as the “downgrade” revision. To illustrate:

# main source tree:1975ea83b712 (add account table) -> ae1027a6acf (add a column)

# branched source tree1975ea83b712 (add account table) -> 27c6a30d7c24 (add shopping cart table)

So above we can see 1975ea83b712 is our branch point. The Alembic command branches illustrates this fact:

$ alembic branchesNone -> 1975ea83b712 (branchpoint), add account table

-> 1975ea83b712 -> 27c6a30d7c24 (head), add shopping cart table-> 1975ea83b712 -> ae1027a6acf (head), add a column

History shows it too, illustrating two head entries as well as a branchpoint:

$ alembic history

1975ea83b712 -> 27c6a30d7c24 (head), add shopping cart table

1975ea83b712 -> ae1027a6acf (head), add a columnNone -> 1975ea83b712 (branchpoint), add account table

Alembic will also refuse to run any migrations until this is resolved:

$ alembic upgrade headINFO [alembic.context] Context class PostgresqlContext.INFO [alembic.context] Will assume transactional DDL.Exception: Only a single head supported so far...

16 Chapter 2. Tutorial

Page 21: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

We resolve this branch by editing the files to be in a straight line. In this case we edit 27c6a30d7c24.py to pointto ae1027a6acf.py:

"""add shopping cart table

Revision ID: 27c6a30d7c24Revises: ae1027a6acf # changed from 1975ea83b712Create Date: 2011-11-08 13:02:14.212810

"""

# revision identifiers, used by Alembic.revision = ’27c6a30d7c24’# changed from 1975ea83b712down_revision = ’ae1027a6acf’

The branches command then shows no branches:

$ alembic branches$

And the history is similarly linear:

$ alembic history

ae1027a6acf -> 27c6a30d7c24 (head), add shopping cart table1975ea83b712 -> ae1027a6acf, add a columnNone -> 1975ea83b712, add account table

Note: A future command called splice will automate this process.

2.12 Building an Up to Date Database from Scratch

There’s a theory of database migrations that says that the revisions in existence for a database should be able to gofrom an entirely blank schema to the finished product, and back again. Alembic can roll this way. Though we think it’skind of overkill, considering that SQLAlchemy itself can emit the full CREATE statements for any given model usingcreate_all(). If you check out a copy of an application, running this will give you the entire database in oneshot, without the need to run through all those migration files, which are instead tailored towards applying incrementalchanges to an existing database.

Alembic can integrate with a create_all() script quite easily. After running the create operation, tell Alembic tocreate a new version table, and to stamp it with the most recent revision (i.e. head):

# inside of a "create the database" script, first create# tables:my_metadata.create_all(engine)

# then, load the Alembic configuration and generate the# version table, "stamping" it with the most recent rev:from alembic.config import Configfrom alembic import commandalembic_cfg = Config("/path/to/yourapp/alembic.ini")command.stamp(alembic_cfg, "head")

When this approach is used, the application can generate the database using normal SQLAlchemy techniques insteadof iterating through hundreds of migration scripts. Now, the purpose of the migration scripts is relegated just to

2.12. Building an Up to Date Database from Scratch 17

Page 22: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

movement between versions on out-of-date databases, not new databases. You can now remove old migration files thatare no longer represented on any existing environments.

To prune old migration files, simply delete the files. Then, in the earliest, still-remaining migration file, setdown_revision to None:

# replace this:#down_revision = ’290696571ad2’

# with this:down_revision = None

That file now becomes the “base” of the migration series.

18 Chapter 2. Tutorial

Page 23: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

CHAPTER 3

Operation Reference

This file provides documentation on Alembic migration directives.

The directives here are used within user-defined migration files, within the upgrade() and downgrade() func-tions, as well as any functions further invoked by those.

All directives exist as methods on a class called Operations. When migration scripts are run, this objectis made available to the script via the alembic.op datamember, which is a proxy to an actual instance ofOperations. Currently, alembic.op is a real Python module, populated with individual proxies for each methodon Operations, so symbols can be imported safely from the alembic.op namespace.

A key design philosophy to the alembic.operations methods is that to the greatest degree possible, they inter-nally generate the appropriate SQLAlchemy metadata, typically involving Table and Constraint objects. This sothat migration instructions can be given in terms of just the string names and/or flags involved. The exceptions to thisrule include the add_column() and create_table() directives, which require full Column objects, thoughthe table metadata is still generated here.

The functions here all require that a MigrationContext has been configured within the env.py script first,which is typically via EnvironmentContext.configure(). Under normal circumstances they are called froman actual migration script, which itself would be invoked by the EnvironmentContext.run_migrations()method.

class alembic.operations.Operations(migration_context)Define high level migration operations.

Each operation corresponds to some schema migration operation, executed against a particularMigrationContext which in turn represents connectivity to a database, or a file output stream.

While Operations is normally configured as part of the EnvironmentContext.run_migrations()method called from an env.py script, a standalone Operations instance can be made for use cases externalto regular Alembic migrations by passing in a MigrationContext:

from alembic.migration import MigrationContextfrom alembic.operations import Operations

conn = myengine.connect()ctx = MigrationContext.configure(conn)op = Operations(ctx)

op.alter_column("t", "c", nullable=True)

add_column(table_name, column)Issue an “add column” instruction using the current migration context.

e.g.:

19

Page 24: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

from alembic import opfrom sqlalchemy import Column, String

op.add_column(’organization’,Column(’name’, String())

)

The provided Column object can also specify a ForeignKey, referencing a remote table name. Alembicwill automatically generate a stub “referenced” table and emit a second ALTER statement in order to addthe constraint separately:

from alembic import opfrom sqlalchemy import Column, INTEGER, ForeignKey

op.add_column(’organization’,Column(’account_id’, INTEGER, ForeignKey(’accounts.id’))

)

Parameters

• table_name – String name of the parent table.

• column – a sqlalchemy.schema.Column object representing the new column.

alter_column(table_name, column_name, nullable=None, server_default=False, name=None,type_=None, existing_type=None, existing_server_default=False, exist-ing_nullable=None)

Issue an “alter column” instruction using the current migration context.

Generally, only that aspect of the column which is being changed, i.e. name, type, nullability, default,needs to be specified. Multiple changes can also be specified at once and the backend should “do the rightthing”, emitting each change either separately or together as the backend allows.

MySQL has special requirements here, since MySQL cannot ALTER a column without a full specifica-tion. When producing MySQL-compatible migration files, it is recommended that the existing_type,existing_server_default, and existing_nullable parameters be present, if not being al-tered.

Type changes which are against the SQLAlchemy “schema” types Boolean and Enum may also addor drop constraints which accompany those types on backends that don’t support them natively. Theexisting_server_default argument is used in this case as well to remove a previous constraint.

Parameters

• table_name – string name of the target table.

• column_name – string name of the target column, as it exists before the operation begins.

• nullable – Optional; specify True or False to alter the column’s nullability.

• server_default – Optional; specify a string SQL expression, text(), orDefaultClause to indicate an alteration to the column’s default value. Set to None tohave the default removed.

• name – Optional; specify a string name here to indicate the new name within a columnrename operation.

• type – Optional; a TypeEngine type object to specify a change to the column’s type. ForSQLAlchemy types that also indicate a constraint (i.e. Boolean, Enum), the constraintis also generated.

20 Chapter 3. Operation Reference

Page 25: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

• existing_type – Optional; a TypeEngine type object to specify the previous type. Thisis required for all MySQL column alter operations that don’t otherwise specify a new type,as well as for when nullability is being changed on a SQL Server column. It is also usedif the type is a so-called SQLlchemy “schema” type which may define a constraint (i.e.Boolean, Enum), so that the constraint can be dropped.

• existing_server_default – Optional; The existing default value of the column. Requiredon MySQL if an existing default is not being changed; else MySQL removes the default.

• existing_nullable – Optional; the existing nullability of the column. Required on MySQLif the existing nullability is not being changed; else MySQL sets this to NULL.

bulk_insert(table, rows)Issue a “bulk insert” operation using the current migration context.

This provides a means of representing an INSERT of multiple rows which works equally well in the contextof executing on a live connection as well as that of generating a SQL script. In the case of a SQL script,the values are rendered inline into the statement.

e.g.:

from datetime import datefrom sqlalchemy.sql import table, columnfrom sqlalchemy import String, Integer, Date

# Create an ad-hoc table to use for the insert statement.accounts_table = table(’account’,

column(’id’, Integer),column(’name’, String),column(’create_date’, Date)

)

bulk_insert(accounts_table,[

{’id’:1, ’name’:’John Smith’,’create_date’:date(2010, 10, 5)},

{’id’:2, ’name’:’Ed Williams’,’create_date’:date(2007, 5, 27)},

{’id’:3, ’name’:’Wendy Jones’,’create_date’:date(2008, 8, 15)},

])

create_check_constraint(name, source, condition, **kw)Issue a “create check constraint” instruction using the current migration context.

e.g.:

from alembic import opfrom sqlalchemy.sql import column, func

op.create_check_constraint("ck_user_name_len","user",func.len(column(’name’)) > 5

)

CHECK constraints are usually against a SQL expression, so ad-hoc table metadata is usually needed. Thefunction will convert the given arguments into a sqlalchemy.schema.CheckConstraint boundto an anonymous table in order to emit the CREATE statement.

21

Page 26: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

Parameters

• name – Name of the check constraint. The name is necessary so that an ALTER statementcan be emitted. For setups that use an automated naming scheme such as that described atNamingConventions, name here can be None, as the event listener will apply the nameto the constraint object when it is associated with the table.

• source – String name of the source table. Currently there is no support for dotted schemanames.

• condition – SQL expression that’s the condition of the constraint. Can be a string orSQLAlchemy expression language structure.

• deferrable – optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE whenissuing DDL for this constraint.

• initially – optional string. If set, emit INITIALLY <value> when issuing DDL for thisconstraint.

create_foreign_key(name, source, referent, local_cols, remote_cols, onupdate=None, on-delete=None)

Issue a “create foreign key” instruction using the current migration context.

e.g.:

from alembic import opop.create_foreign_key(

"fk_user_address", "address","user", ["user_id"], ["id"])

This internally generates a Table object containing the necessary columns, then generates a newForeignKeyConstraint object which it then associates with the Table. Any event listeners as-sociated with this action will be fired off normally. The AddConstraint construct is ultimately used togenerate the ALTER statement.

Parameters

• name – Name of the foreign key constraint. The name is necessary so that an ALTERstatement can be emitted. For setups that use an automated naming scheme such as thatdescribed at NamingConventions, name here can be None, as the event listener will applythe name to the constraint object when it is associated with the table.

• source – String name of the source table. Currently there is no support for dotted schemanames.

• referent – String name of the destination table. Currently there is no support for dottedschema names.

• local_cols – a list of string column names in the source table.

• remote_cols – a list of string column names in the remote table.

• onupdate – Optional string. If set, emit ON UPDATE <value> when issuing DDL for thisconstraint. Typical values include CASCADE, DELETE and RESTRICT.

• ondelete – Optional string. If set, emit ON DELETE <value> when issuing DDL for thisconstraint. Typical values include CASCADE, DELETE and RESTRICT.

create_index(name, tablename, *columns, **kw)Issue a “create index” instruction using the current migration context.

e.g.:

22 Chapter 3. Operation Reference

Page 27: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

from alembic import opop.create_index(’ik_test’, ’t1’, [’foo’, ’bar’])

create_table(name, *columns, **kw)Issue a “create table” instruction using the current migration context.

This directive receives an argument list similar to that of the traditional sqlalchemy.schema.Tableconstruct, but without the metadata:

from sqlalchemy import INTEGER, VARCHAR, NVARCHAR, Columnfrom alembic import op

op.create_table(’accounts’,Column(’id’, INTEGER, primary_key=True),Column(’name’, VARCHAR(50), nullable=False),Column(’description’, NVARCHAR(200))

)

Parameters

• name – Name of the table

• *columns – collection of Column objects within the table, as well as optionalConstraint objects and Index objects.

• emit_events – if True, emit before_create and after_create events when thetable is being created. In particular, the Postgresql ENUM type will emit a CREATE TYPEwithin these events.

• **kw – Other keyword arguments are passed to the underlying Table object created forthe command.

create_unique_constraint(name, source, local_cols, **kw)Issue a “create unique constraint” instruction using the current migration context.

e.g.:

from alembic import opop.create_unique_constraint("uq_user_name", "user", ["name"])

This internally generates a Table object containing the necessary columns, then generates a newUniqueConstraint object which it then associates with the Table. Any event listeners associatedwith this action will be fired off normally. The AddConstraint construct is ultimately used to generatethe ALTER statement.

Parameters

• name – Name of the unique constraint. The name is necessary so that an ALTER statementcan be emitted. For setups that use an automated naming scheme such as that described atNamingConventions, name here can be None, as the event listener will apply the nameto the constraint object when it is associated with the table.

• source – String name of the source table. Currently there is no support for dotted schemanames.

• local_cols – a list of string column names in the source table.

• deferrable – optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE whenissuing DDL for this constraint.

23

Page 28: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

• initially – optional string. If set, emit INITIALLY <value> when issuing DDL for thisconstraint.

drop_column(table_name, column_name, **kw)Issue a “drop column” instruction using the current migration context.

e.g.:

drop_column(’organization’, ’account_id’)

Parameters

• table_name – name of table

• column_name – name of column

• mssql_drop_check – Optional boolean. When True, on Microsoft SQL Server only,first drop the CHECK constraint on the column using a SQL-script-compatible block thatselects into a @variable from sys.check_constraints, then exec’s a separate DROP CON-STRAINT for that constraint.

• mssql_drop_default – Optional boolean. When True, on Microsoft SQL Server only,first drop the DEFAULT constraint on the column using a SQL-script-compatible blockthat selects into a @variable from sys.default_constraints, then exec’s a separate DROPCONSTRAINT for that default.

drop_constraint(name, tablename)Drop a constraint of the given name

drop_index(name, tablename=None)Issue a “drop index” instruction using the current migration context.

e.g.:

drop_index("accounts")

Parameters tablename – name of the owning table. Some backends such as Microsoft SQLServer require this.

drop_table(name)Issue a “drop table” instruction using the current migration context.

e.g.:

drop_table("accounts")

execute(sql, execution_options=None)Execute the given SQL using the current migration context.

In a SQL script context, the statement is emitted directly to the output stream. There is no return result,however, as this function is oriented towards generating a change script that can run in “offline” mode. Forfull interaction with a connected database, use the “bind” available from the context:

from alembic import opconnection = op.get_bind()

Also note that any parameterized statement here will not work in offline mode - INSERT, UPDATE andDELETE statements which refer to literal values would need to render inline expressions. For simple usecases, the inline_literal() function can be used for rudimentary quoting of string values. For“bulk” inserts, consider using bulk_insert().

24 Chapter 3. Operation Reference

Page 29: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

For example, to emit an UPDATE statement which is equally compatible with both online and offlinemode:

from sqlalchemy.sql import table, columnfrom sqlalchemy import Stringfrom alembic import op

account = table(’account’,column(’name’, String)

)op.execute(

account.update().\where(account.c.name==op.inline_literal(’account 1’)).\values({’name’:op.inline_literal(’account 2’)}))

Note above we also used the SQLAlchemy sqlalchemy.sql.expression.table() andsqlalchemy.sql.expression.column() constructs to make a brief, ad-hoc table construct justfor our UPDATE statement. A full Table construct of course works perfectly fine as well, though note it’sa recommended practice to at least ensure the definition of a table is self-contained within the migrationscript, rather than imported from a module that may break compatibility with older migrations.

Parameters sql – Any legal SQLAlchemy expression, including:

•a string

•a sqlalchemy.sql.expression.text() construct.

•a sqlalchemy.sql.expression.insert() construct.

•a sqlalchemy.sql.expression.update(), sqlalchemy.sql.expression.insert(),or sqlalchemy.sql.expression.delete() construct.

•Pretty much anything that’s “executable” as described in SQL Expression Language Tutorial.

Parameters execution_options – Optional dictionary of execution options, will be passed tosqlalchemy.engine.base.Connection.execution_options().

get_bind()Return the current ‘bind’.

Under normal circumstances, this is the Connection currently being used to emit SQL to the database.

In a SQL script context, this value is None. [TODO: verify this]

get_context()Return the MigrationContext object that’s currently in use.

inline_literal(value, type_=None)Produce an ‘inline literal’ expression, suitable for using in an INSERT, UPDATE, or DELETE statement.

When using Alembic in “offline” mode, CRUD operations aren’t compatible with SQLAlchemy’s defaultbehavior surrounding literal values, which is that they are converted into bound values and passed sep-arately into the execute() method of the DBAPI cursor. An offline SQL script needs to have theserendered inline. While it should always be noted that inline literal values are an enormous security holein an application that handles untrusted input, a schema migration is not run in this context, so literalsare safe to render inline, with the caveat that advanced types like dates may not be supported directly bySQLAlchemy.

See execute() for an example usage of inline_literal().

25

Page 30: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

Parameters

• value – The value to render. Strings, integers, and simple numerics should be supported.Other types like boolean, dates, etc. may or may not be supported yet by various backends.

• type – optional - a sqlalchemy.types.TypeEngine subclass stating the type ofthis value. In SQLAlchemy expressions, this is usually derived automatically from thePython type of the value itself, as well as based on the context in which the value is used.

rename_table(old_table_name, new_table_name, schema=None)Emit an ALTER TABLE to rename a table.

Parameters

• old_table_name – old name.

• new_table_name – new name.

• schema – Optional, name of schema to operate within.

26 Chapter 3. Operation Reference

Page 31: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

CHAPTER 4

API Details

This section describes some key functions used within the migration process, particularly those referenced within amigration environment’s env.py file.

4.1 Overview

The three main objects in use are the EnvironmentContext, MigrationContext, and Operations classes,pictured below.

An Alembic command begins by instantiating an EnvironmentContext object, then making it avail-able via the alembic.context proxy module. The env.py script, representing a user-configurablemigration environment, is then invoked. The env.py script is then responsible for calling upon theEnvironmentContext.configure(), whose job it is to create a MigrationContext object.

Before this method is called, there’s not yet any database connection or dialect-specific state set up. While manymethods on EnvironmentContext are usable at this stage, those which require database access, or at least ac-cess to the kind of database dialect in use, are not. Once the EnvironmentContext.configure() methodis called, the EnvironmentContext is said to be configured with database connectivity, available via a new

27

Page 32: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

MigrationContext object. The MigrationContext is associated with the EnvironmentContext objectvia the EnvironmentContext.get_context() method.

Finally, env.py calls upon the EnvironmentContext.run_migrations() method. Within this method, anew Operations object, which provides an API for individual database migration operations, is established withinthe alembic.op proxy module. The Operations object uses the MigrationContext object ultimately as asource of database connectivity, though in such a way that it does not care if the MigrationContext is talking toa real database or just writing out SQL to a file.

4.2 env.py Directives

This section covers the objects that are generally used within an env.py environmental configuration script. Alembicnormally generates this script for you; it is however made available locally within the migrations environment so thatit can be customized.

In particular, the key method used within env.py is EnvironmentContext.configure(), which establishesall the details about how the database will be accessed.

sqlalchemy.engine.engine_from_config(configuration, prefix=’sqlalchemy.’, **kwargs)Create a new Engine instance using a configuration dictionary.

The dictionary is typically produced from a config file where keys are prefixed, such as sqlalchemy.url,sqlalchemy.echo, etc. The ‘prefix’ argument indicates the prefix to be searched for.

A select set of keyword arguments will be “coerced” to their expected type based on string values. In a futurerelease, this functionality will be expanded and include dialect-specific arguments.

class alembic.environment.EnvironmentContext(config, script, **kw)Represent the state made available to an env.py script.

EnvironmentContext is normally instantiated by the commands present in the alembic.commandmodule. From within an env.py script, the current EnvironmentContext is available via thealembic.context datamember.

begin_transaction()Return a context manager that will enclose an operation within a “transaction”, as defined by the environ-ment’s offline and transactional DDL settings.

e.g.:

with context.begin_transaction():context.run_migrations()

begin_transaction() is intended to “do the right thing” regardless of calling context:

•If is_transactional_ddl() is False, returns a “do nothing” context manager which other-wise produces no transactional state or directives.

•If is_offline_mode() is True, returns a context manager that will invoke theDefaultImpl.emit_begin() and DefaultImpl.emit_commit() methods, which willproduce the string directives BEGIN and COMMIT on the output stream, as rendered by the targetbackend (e.g. SQL Server would emit BEGIN TRANSACTION).

•Otherwise, calls sqlalchemy.engine.base.Connection.begin() on the current onlineconnection, which returns a sqlalchemy.engine.base.Transaction object. This objectdemarcates a real transaction and is itself a context manager, which will roll back if an exception israised.

28 Chapter 4. API Details

Page 33: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

Note that a custom env.py script which has more specific transactional needs can of course manipulatethe Connection directly to produce transactional state in “online” mode.

config = NoneAn instance of Config representing the configuration file contents as well as other variables set program-matically within it.

configure(connection=None, url=None, dialect_name=None, transactional_ddl=None, out-put_buffer=None, starting_rev=None, tag=None, target_metadata=None, com-pare_type=False, compare_server_default=False, upgrade_token=’upgrades’,downgrade_token=’downgrades’, alembic_module_prefix=’op.’,sqlalchemy_module_prefix=’sa.’, **kw)

Configure a MigrationContext within this EnvironmentContext which will provide databaseconnectivity and other configuration to a series of migration scripts.

Many methods on EnvironmentContext require that this method has been called in order to function,as they ultimately need to have database access or at least access to the dialect in use. Those which do aredocumented as such.

The important thing needed by configure() is a means to determine what kind of database dialect isin use. An actual connection to that database is needed only if the MigrationContext is to be used in“online” mode.

If the is_offline_mode() function returns True, then no connection is neededhere. Otherwise, the connection parameter should be present as an instance ofsqlalchemy.engine.base.Connection.

This function is typically called from the env.py script within a migration environment. It can be calledmultiple times for an invocation. The most recent Connection for which it was called is the one thatwill be operated upon by the next call to run_migrations().

General parameters:

Parameters

• connection – a Connection to use for SQL execution in “online” mode. When present,is also used to determine the type of dialect in use.

• url – a string database url, or a sqlalchemy.engine.url.URL object. The type ofdialect to be used will be derived from this if connection is not passed.

• dialect_name – string name of a dialect, such as “postgresql”, “mssql”, etc. The type ofdialect to be used will be derived from this if connection and url are not passed.

• transactional_ddl – Force the usage of “transactional” DDL on or off; this otherwisedefaults to whether or not the dialect in use supports it.

• output_buffer – a file-like object that will be used for textual output when the --sqloption is used to generate SQL scripts. Defaults to sys.stdout if not passed here andalso not present on the Config object. The value here overrides that of the Configobject.

• starting_rev – Override the “starting revision” argument when using --sql mode.

• tag – a string tag for usage by custom env.py scripts. Set via the --tag option, can beoverridden here.

Parameters specific to the autogenerate feature, when alembic revision is run with the--autogenerate feature:

Parameters

4.2. env.py Directives 29

Page 34: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

• target_metadata – a sqlalchemy.schema.MetaData object that will be consultedduring autogeneration. The tables present will be compared against what is locally avail-able on the target Connection to produce candidate upgrade/downgrade operations.

• compare_type – Indicates type comparison behavior during an autogenerate operation.Defaults to False which disables type comparison. Set to True to turn on default typecomparison, which has varied accuracy depending on backend.

To customize type comparison behavior, a callable may be specified which can filter typecomparisons during an autogenerate operation. The format of this callable is:

def my_compare_type(context, inspected_column,metadata_column, inspected_type, metadata_type):

# return True if the types are different,# False if not, or None to allow the default implementation# to compare these typespass

inspected_column is a dictionary structure as returned bysqlalchemy.engine.reflection.Inspector.get_columns(), whereasmetadata_column is a sqlalchemy.schema.Column from the local modelenvironment.

A return value of None indicates to allow default type comparison to proceed.

• compare_server_default – Indicates server default comparison behavior during an au-togenerate operation. Defaults to False which disables server default comparison. Setto True to turn on server default comparison, which has varied accuracy depending onbackend.

To customize server default comparison behavior, a callable may be specified which canfilter server default comparisons during an autogenerate operation. defaults during anautogenerate operation. The format of this callable is:

def my_compare_server_default(context, inspected_column,metadata_column, inspected_default, metadata_default,rendered_metadata_default):

# return True if the defaults are different,# False if not, or None to allow the default implementation# to compare these defaultspass

inspected_column is a dictionary structure as returned bysqlalchemy.engine.reflection.Inspector.get_columns(), whereasmetadata_column is a sqlalchemy.schema.Column from the local modelenvironment.

A return value of None indicates to allow default server default comparison to proceed.Note that some backends such as Postgresql actually execute the two defaults on thedatabase side to compare for equivalence.

• upgrade_token – When autogenerate completes, the text of the candidate upgrade op-erations will be present in this template variable when script.py.mako is rendered.Defaults to upgrades.

• downgrade_token – When autogenerate completes, the text of the candidate downgradeoperations will be present in this template variable when script.py.mako is rendered.Defaults to downgrades.

30 Chapter 4. API Details

Page 35: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

• alembic_module_prefix – When autogenerate refers to Alembicalembic.operations constructs, this prefix will be used (i.e. op.create_table)Defaults to “op.”. Can be None to indicate no prefix.

• sqlalchemy_module_prefix – When autogenerate refers to SQLAlchemy Columnor type classes, this prefix will be used (i.e. sa.Column("somename",sa.Integer)) Defaults to “sa.”. Can be None to indicate no prefix. Note that whendialect-specific types are rendered, autogenerate will render them using the dialect modulename, i.e. mssql.BIT(), postgresql.UUID().

Parameters specific to individual backends:

Parameters mssql_batch_separator – The “batch separator” which will be placed betweeneach statement when generating offline SQL Server migrations. Defaults to GO. Note this isin addition to the customary semicolon ; at the end of each statement; SQL Server considersthe “batch separator” to denote the end of an individual statement execution, and cannotgroup certain dependent operations in one step.

execute(sql, execution_options=None)Execute the given SQL using the current change context.

The behavior of execute() is the same as that of Operations.execute(). Please see that func-tion’s documentation for full detail including caveats and limitations.

This function requires that a MigrationContext has first been made available via configure().

get_bind()Return the current ‘bind’.

In “online” mode, this is the sqlalchemy.engine.base.Connection currently being used to emitSQL to the database.

This function requires that a MigrationContext has first been made available via configure().

get_context()Return the current MigrationContext object.

If EnvironmentContext.configure() has not been called yet, raises an exception.

get_head_revision()Return the hex identifier of the ‘head’ revision.

This function does not require that the MigrationContext has been configured.

get_revision_argument()Get the ‘destination’ revision argument.

This is typically the argument passed to the upgrade or downgrade command.

If it was specified as head, the actual version number is returned; if specified as base, None is returned.

This function does not require that the MigrationContext has been configured.

get_starting_revision_argument()Return the ‘starting revision’ argument, if the revision was passed using start:end.

This is only meaningful in “offline” mode. Returns None if no value is available or was configured.

This function does not require that the MigrationContext has been configured.

get_tag_argument()Return the value passed for the --tag argument, if any.

The --tag argument is not used directly by Alembic, but is available for custom env.py configurationsthat wish to use it; particularly for offline generation scripts that wish to generate tagged filenames.

4.2. env.py Directives 31

Page 36: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

This function does not require that the MigrationContext has been configured.

is_offline_mode()Return True if the current migrations environment is running in “offline mode”.

This is True or False depending on the the --sql flag passed.

This function does not require that the MigrationContext has been configured.

is_transactional_ddl()Return True if the context is configured to expect a transactional DDL capable backend.

This defaults to the type of database in use, and can be overridden by the transactional_ddl argu-ment to configure()

This function requires that a MigrationContext has first been made available via configure().

run_migrations(**kw)Run migrations as determined by the current command line configuration as well as versioning informationpresent (or not) in the current database connection (if one is present).

The function accepts optional **kw arguments. If these are passed, they are sent directly to theupgrade() and downgrade() functions within each target revision file. By modifying thescript.py.mako file so that the upgrade() and downgrade() functions accept arguments, pa-rameters can be passed here so that contextual information, usually information to identify a particulardatabase in use, can be passed from a custom env.py script to the migration functions.

This function requires that a MigrationContext has first been made available via configure().

script = NoneAn instance of ScriptDirectory which provides programmatic access to version files within theversions/ directory.

static_output(text)Emit text directly to the “offline” SQL stream.

Typically this is for emitting comments that start with –. The statement is not treated as a SQL execution,no ; or batch separator is added, etc.

alembic.environment.configurealias of EnvironmentContext

class alembic.migration.MigrationContext(dialect, connection, opts)Represent the state made available to a migration script, or otherwise a series of migration operations.

Mediates the relationship between an env.py environment script, a ScriptDirectory instance, and aDefaultImpl instance.

The MigrationContext that’s established for a duration of a migration command is available via theEnvironmentContext.get_context() method, which is available at alembic.context:

from alembic import contextmigration_context = context.get_context()

A MigrationContext can be created programmatically for usage outside of the usual Alembic migrationsflow, using the MigrationContext.configure() method:

conn = myengine.connect()ctx = MigrationContext.configure(conn)

The above context can then be used to produce Alembic migration operations with an Operations instance.

bindReturn the current “bind”.

32 Chapter 4. API Details

Page 37: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

In online mode, this is an instance of sqlalchemy.engine.base.Connection, andis suitable for ad-hoc execution of any kind of usage described in SQL Expression Lan-guage Tutorial as well as for usage with the sqlalchemy.schema.Table.create() andsqlalchemy.schema.MetaData.create_all() methods of Table, MetaData.

Note that when “standard output” mode is enabled, this bind will be a “mock” connection handler thatcannot return results and is only appropriate for a very limited subset of commands.

classmethod configure(connection=None, url=None, dialect_name=None, opts={})Create a new MigrationContext.

This is a factory method usually called by EnvironmentContext.configure().

Parameters

• connection – a Connection to use for SQL execution in “online” mode. When present,is also used to determine the type of dialect in use.

• url – a string database url, or a sqlalchemy.engine.url.URL object. The type ofdialect to be used will be derived from this if connection is not passed.

• dialect_name – string name of a dialect, such as “postgresql”, “mssql”, etc. The type ofdialect to be used will be derived from this if connection and url are not passed.

• opts – dictionary of options. Most other options accepted byEnvironmentContext.configure() are passed via this dictionary.

alembic.migration.text(text, bind=None, bindparams=None, typemap=None, autocommit=None)Construct a new TextClause clause, representing a textual SQL string directly.

E.g.:

fom sqlalchemy import text

t = text("SELECT * FROM users")result = connection.execute(t)

The advantages text() provides over a plain string are backend-neutral support for bind parameters,per-statement execution options, as well as bind parameter and result-column typing behavior, allowingSQLAlchemy type constructs to play a role when executing a statement that is specified literally. The con-struct can also be provided with a .c collection of column elements, allowing it to be embedded in other SQLexpression constructs as a subquery.

Bind parameters are specified by name, using the format :name. E.g.:

t = text("SELECT * FROM users WHERE id=:user_id")result = connection.execute(t, user_id=12)

For SQL statements where a colon is required verbatim, as within an inline string, use a backslash to escape:

t = text("SELECT * FROM users WHERE name=’\:username’")

The TextClause construct includes methods which can provide information about the bound parameters aswell as the column values which would be returned from the textual statement, assuming it’s an executableSELECT type of statement. The TextClause.bindparams() method is used to provide bound parameterdetail, and TextClause.columns() method allows specification of return columns including names andtypes:

t = text("SELECT * FROM users WHERE id=:user_id").\bindparams(user_id=7).\columns(id=Integer, name=String)

4.2. env.py Directives 33

Page 38: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

for id, name in connection.execute(t):print(id, name)

The text() construct is used internally in cases when a literal string is specified for part of a larger query,such as when a string is specified to the Select.where() method of Select. In those cases, the same bindparameter syntax is applied:

s = select([users.c.id, users.c.name]).where("id=:user_id")result = connection.execute(s, user_id=12)

Using text() explicitly usually implies the construction of a full, standalone state-ment. As such, SQLAlchemy refers to it as an Executable object, and it supports theExecutable.execution_options() method. For example, a text() construct that should besubject to “autocommit” can be set explicitly so using the autocommit option:

t = text("EXEC my_procedural_thing()").\execution_options(autocommit=True)

Note that SQLAlchemy’s usual “autocommit” behavior applies to text() constructs implicitly - that is, state-ments which begin with a phrase such as INSERT, UPDATE, DELETE, or a variety of other phrases specific tocertain backends, will be eligible for autocommit if no transaction is in progress.

Parameters

• text – the text of the SQL statement to be created. use :<param> to specify bind parame-ters; they will be compiled to their engine-specific format.

• autocommit – Deprecated. Use .execution_options(autocommit=<True|False>) to set theautocommit option.

• bind – an optional connection or engine to be used for this text query.

• bindparams – Deprecated. A list of bindparam() instances used to provide infor-mation about parameters embedded in the statement. This argument now invokes theTextClause.bindparams() method on the construct before returning it. E.g.:

stmt = text("SELECT * FROM table WHERE id=:id",bindparams=[bindparam(’id’, value=5, type_=Integer)])

Is equivalent to:

stmt = text("SELECT * FROM table WHERE id=:id").\bindparams(bindparam(’id’, value=5, type_=Integer))

Deprecated since version 0.9.0: the TextClause.bindparams() method supersedesthe bindparams argument to text().

• typemap – Deprecated. A dictionary mapping the names of columns represented inthe columns clause of a SELECT statement to type objects, which will be used to per-form post-processing on columns within the result set. This parameter now invokes theTextClause.columns() method, which returns a TextAsFrom construct that gainsa .c collection and can be embedded in other expressions. E.g.:

stmt = text("SELECT * FROM table",typemap={’id’: Integer, ’name’: String},

)

Is equivalent to:

34 Chapter 4. API Details

Page 39: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

stmt = text("SELECT * FROM table").columns(id=Integer, name=String)

Or alternatively:

from sqlalchemy.sql import columnstmt = text("SELECT * FROM table").columns(

column(’id’, Integer),column(’name’, String)

)

Deprecated since version 0.9.0: the TextClause.columns() method supersedes thetypemap argument to text().

4.3 Commands

Alembic commands are all represented by functions in the alembic.command package. They all accept the samestyle of usage, being sent the Config object as the first argument.

Commands can be run programmatically, by first constructing a Config object, as in:

from alembic.config import Configfrom alembic import commandalembic_cfg = Config("/path/to/yourapp/alembic.ini")command.upgrade(alembic_cfg, "head")

alembic.command.branches(config)Show current un-spliced branch points

alembic.command.current(config)Display the current revision for each database.

alembic.command.downgrade(config, revision, sql=False, tag=None)Revert to a previous version.

alembic.command.history(config)List changeset scripts in chronological order.

alembic.command.init(config, directory, template=’generic’)Initialize a new scripts directory.

alembic.command.list_templates(config)List available templates

alembic.command.revision(config, message=None, autogenerate=False)Create a new revision file.

alembic.command.splice(config, parent, child)‘splice’ two branches, creating a new revision file.

this command isn’t implemented right now.

alembic.command.stamp(config, revision, sql=False, tag=None)‘stamp’ the revision table with the given revision; don’t run any migrations.

alembic.command.upgrade(config, revision, sql=False, tag=None)Upgrade to a later version.

4.3. Commands 35

Page 40: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

4.4 Configuration

class alembic.config.Config(file_=None, ini_section=’alembic’, output_buffer=None)Represent an Alembic configuration.

Within an env.py script, this is available via the EnvironmentContext.config attribute, which in turnis available at alembic.context:

from alembic import context

some_param = context.config.get_main_option("my option")

When invoking Alembic programatically, a new Config can be created by passing the name of an .ini file tothe constructor:

from alembic.config import Configalembic_cfg = Config("/path/to/yourapp/alembic.ini")

With a Config object, you can then run Alembic commands programmatically using the directives inalembic.command.

The Config object can also be constructed without a filename. Values can be set programmatically, and newsections will be created as needed:

from alembic.config import Configalembic_cfg = Config()alembic_cfg.set_main_option("url", "postgresql://foo/bar")alembic_cfg.set_section_option("mysection", "foo", "bar")

Parameters

• file – name of the .ini file to open.

• ini_section – name of the main Alembic section within the .ini file

• output_buffer – optional file-like input buffer which will be passed to theMigrationContext - used to redirect access when using Alembic programmatically.

config_file_name = NoneFilesystem path to the .ini file in use.

config_ini_section = NoneName of the config file section to read basic configuration from. Defaults to alembic, that is the[alembic] section of the .ini file. This value is modified using the -n/--name option to the Alembicrunnier.

file_config = None

get_main_option(name, default=None)Return an option from the ‘main’ section of the .ini file.

This defaults to being a key from the [alembic] section, unless the -n/--name flag were used toindicate a different section.

get_section(name)Return all the configuration options from a given .ini file section as a dictionary.

get_section_option(section, name, default=None)Return an option from the given section of the .ini file.

36 Chapter 4. API Details

Page 41: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

get_template_directory()Return the directory where Alembic setup templates are found.

This method is used by the alembic init and list_templates commands.

remove_main_option(name)

set_main_option(name, value)Set an option programmatically within the ‘main’ section.

This overrides whatever was in the .ini file.

set_section_option(section, name, value)Set an option programmatically within the given section.

The section is created if it doesn’t exist already. The value here will override whatever was in the .ini file.

alembic.config.main(argv=None, **kwargs)The console runner function for Alembic.

4.5 Internals

class alembic.script.Script(module, rev_id, path)Represent a single revision file in a versions/ directory.

add_nextrev(rev)

doc

classmethod from_filename(dir_, filename)

classmethod from_path(path)

is_branch_point

is_head

nextrev = frozenset([])

class alembic.script.ScriptDirectory(dir, file_template=’%(rev)s_%(slug)s’)Provides operations upon an Alembic script directory.

copy_file(src, dest)

downgrade_to(destination, current_rev, context)

env_py_location

classmethod from_config(config)

generate_rev(revid, message, refresh=False, **kw)

generate_template(src, dest, **kw)

run_env()Run the script environment.

This basically runs the env.py script present in the migration environment. It is called exclusively by thecommand functions in alembic.command.

upgrade_from(destination, current_rev, context)

4.5. Internals 37

Page 42: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

walk_revisions()Iterate through all revisions.

This is actually a breadth-first tree traversal, with leaf nodes being heads.

4.5.1 DDL Internals

class alembic.ddl.base.AddColumn(name, column, schema=None)

class alembic.ddl.base.AlterColumn(name, column_name, schema=None, existing_type=None, ex-isting_nullable=None, existing_server_default=None)

class alembic.ddl.base.AlterTable(table_name, schema=None)Represent an ALTER TABLE statement.

Only the string name and optional schema name of the table is required, not a full Table object.

class alembic.ddl.base.ColumnDefault(name, column_name, default, **kw)

class alembic.ddl.base.ColumnName(name, column_name, newname, **kw)

class alembic.ddl.base.ColumnNullable(name, column_name, nullable, **kw)

class alembic.ddl.base.ColumnType(name, column_name, type_, **kw)

class alembic.ddl.base.DropColumn(name, column, schema=None)

class alembic.ddl.base.RenameTable(old_table_name, new_table_name, schema=None)

alembic.ddl.base.add_column(compiler, column, **kw)

alembic.ddl.base.alter_column(compiler, name)

alembic.ddl.base.alter_table(compiler, name, schema)

alembic.ddl.base.drop_column(compiler, name)

alembic.ddl.base.format_column_name(compiler, name)

alembic.ddl.base.format_server_default(compiler, default)

alembic.ddl.base.format_table_name(compiler, name, schema)

alembic.ddl.base.format_type(compiler, type_)

alembic.ddl.base.quote_dotted(name, quote)quote the elements of a dotted name

alembic.ddl.base.visit_add_column(element, compiler, **kw)

alembic.ddl.base.visit_column_default(element, compiler, **kw)

alembic.ddl.base.visit_column_name(element, compiler, **kw)

alembic.ddl.base.visit_column_nullable(element, compiler, **kw)

alembic.ddl.base.visit_column_type(element, compiler, **kw)

alembic.ddl.base.visit_drop_column(element, compiler, **kw)

alembic.ddl.base.visit_rename_table(element, compiler, **kw)

class alembic.ddl.impl.DefaultImpl(dialect, connection, as_sql, transactional_ddl, output_buffer,context_opts)

Provide the entrypoint for major migration operations, including database-specific behavioral variances.

38 Chapter 4. API Details

Page 43: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

While individual SQL/DDL constructs already provide for database-specific implementations, variances hereallow for entirely different sequences of operations to take place for a particular migration, such as SQL Server’sspecial ‘IDENTITY INSERT’ step for bulk inserts.

add_column(table_name, column)

add_constraint(const)

alter_column(table_name, column_name, nullable=None, server_default=False, name=None,type_=None, schema=None, existing_type=None, existing_server_default=None, ex-isting_nullable=None)

bind

bulk_insert(table, rows)

compare_server_default(inspector_column, metadata_column, rendered_metadata_default)

compare_type(inspector_column, metadata_column)

create_index(index)

create_table(table)

drop_column(table_name, column, **kw)

drop_constraint(const)

drop_index(index)

drop_table(table)

emit_begin()Emit the string BEGIN, or the backend-specific equivalent, on the current connection context.

This is used in offline mode and typically via EnvironmentContext.begin_transaction().

emit_commit()Emit the string COMMIT, or the backend-specific equivalent, on the current connection context.

This is used in offline mode and typically via EnvironmentContext.begin_transaction().

execute(sql, execution_options=None)

classmethod get_by_dialect(dialect)

rename_table(old_table_name, new_table_name, schema=None)

start_migrations()A hook called when EnvironmentContext.run_migrations() is called.

Implementations can set up per-migration-run state here.

static_output(text)

transactional_ddl = False

class alembic.ddl.impl.ImplMeta(classname, bases, dict_)

alembic.ddl.impl.text(text, bind=None, bindparams=None, typemap=None, autocommit=None)Construct a new TextClause clause, representing a textual SQL string directly.

E.g.:

fom sqlalchemy import text

t = text("SELECT * FROM users")result = connection.execute(t)

4.5. Internals 39

Page 44: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

The advantages text() provides over a plain string are backend-neutral support for bind parameters,per-statement execution options, as well as bind parameter and result-column typing behavior, allowingSQLAlchemy type constructs to play a role when executing a statement that is specified literally. The con-struct can also be provided with a .c collection of column elements, allowing it to be embedded in other SQLexpression constructs as a subquery.

Bind parameters are specified by name, using the format :name. E.g.:

t = text("SELECT * FROM users WHERE id=:user_id")result = connection.execute(t, user_id=12)

For SQL statements where a colon is required verbatim, as within an inline string, use a backslash to escape:

t = text("SELECT * FROM users WHERE name=’\:username’")

The TextClause construct includes methods which can provide information about the bound parameters aswell as the column values which would be returned from the textual statement, assuming it’s an executableSELECT type of statement. The TextClause.bindparams() method is used to provide bound parameterdetail, and TextClause.columns() method allows specification of return columns including names andtypes:

t = text("SELECT * FROM users WHERE id=:user_id").\bindparams(user_id=7).\columns(id=Integer, name=String)

for id, name in connection.execute(t):print(id, name)

The text() construct is used internally in cases when a literal string is specified for part of a larger query,such as when a string is specified to the Select.where() method of Select. In those cases, the same bindparameter syntax is applied:

s = select([users.c.id, users.c.name]).where("id=:user_id")result = connection.execute(s, user_id=12)

Using text() explicitly usually implies the construction of a full, standalone state-ment. As such, SQLAlchemy refers to it as an Executable object, and it supports theExecutable.execution_options() method. For example, a text() construct that should besubject to “autocommit” can be set explicitly so using the autocommit option:

t = text("EXEC my_procedural_thing()").\execution_options(autocommit=True)

Note that SQLAlchemy’s usual “autocommit” behavior applies to text() constructs implicitly - that is, state-ments which begin with a phrase such as INSERT, UPDATE, DELETE, or a variety of other phrases specific tocertain backends, will be eligible for autocommit if no transaction is in progress.

Parameters

• text – the text of the SQL statement to be created. use :<param> to specify bind parame-ters; they will be compiled to their engine-specific format.

• autocommit – Deprecated. Use .execution_options(autocommit=<True|False>) to set theautocommit option.

• bind – an optional connection or engine to be used for this text query.

• bindparams – Deprecated. A list of bindparam() instances used to provide infor-mation about parameters embedded in the statement. This argument now invokes theTextClause.bindparams() method on the construct before returning it. E.g.:

40 Chapter 4. API Details

Page 45: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

stmt = text("SELECT * FROM table WHERE id=:id",bindparams=[bindparam(’id’, value=5, type_=Integer)])

Is equivalent to:

stmt = text("SELECT * FROM table WHERE id=:id").\bindparams(bindparam(’id’, value=5, type_=Integer))

Deprecated since version 0.9.0: the TextClause.bindparams() method supersedesthe bindparams argument to text().

• typemap – Deprecated. A dictionary mapping the names of columns represented inthe columns clause of a SELECT statement to type objects, which will be used to per-form post-processing on columns within the result set. This parameter now invokes theTextClause.columns() method, which returns a TextAsFrom construct that gainsa .c collection and can be embedded in other expressions. E.g.:

stmt = text("SELECT * FROM table",typemap={’id’: Integer, ’name’: String},

)

Is equivalent to:

stmt = text("SELECT * FROM table").columns(id=Integer, name=String)

Or alternatively:

from sqlalchemy.sql import columnstmt = text("SELECT * FROM table").columns(

column(’id’, Integer),column(’name’, String)

)

Deprecated since version 0.9.0: the TextClause.columns() method supersedes thetypemap argument to text().

MySQL

class alembic.ddl.mysql.MySQLAlterColumn(name, column_name, schema=None, new-name=None, type_=None, nullable=None, de-fault=False)

Bases: alembic.ddl.base.AlterColumn

class alembic.ddl.mysql.MySQLImpl(dialect, connection, as_sql, transactional_ddl, output_buffer,context_opts)

Bases: alembic.ddl.impl.DefaultImpl

alter_column(table_name, column_name, nullable=None, server_default=False, name=None,type_=None, schema=None, existing_type=None, existing_server_default=None, ex-isting_nullable=None)

4.5. Internals 41

Page 46: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

MS-SQL

class alembic.ddl.mssql.MSSQLImpl(*arg, **kw)Bases: alembic.ddl.impl.DefaultImpl

alter_column(table_name, column_name, nullable=None, server_default=False, name=None,type_=None, schema=None, existing_type=None, existing_server_default=None, ex-isting_nullable=None)

batch_separator = ‘GO’

bulk_insert(table, rows)

drop_column(table_name, column, **kw)

emit_begin()

transactional_ddl = True

alembic.ddl.mssql.mssql_add_column(compiler, column, **kw)

alembic.ddl.mssql.visit_add_column(element, compiler, **kw)

alembic.ddl.mssql.visit_column_default(element, compiler, **kw)

alembic.ddl.mssql.visit_column_nullable(element, compiler, **kw)

alembic.ddl.mssql.visit_column_type(element, compiler, **kw)

alembic.ddl.mssql.visit_rename_column(element, compiler, **kw)

Postgresql

class alembic.ddl.postgresql.PostgresqlImpl(dialect, connection, as_sql, transactional_ddl,output_buffer, context_opts)

Bases: alembic.ddl.impl.DefaultImpl

compare_server_default(inspector_column, metadata_column, rendered_metadata_default)

transactional_ddl = True

SQLite

class alembic.ddl.sqlite.SQLiteImpl(dialect, connection, as_sql, transactional_ddl, out-put_buffer, context_opts)

Bases: alembic.ddl.impl.DefaultImpl

transactional_ddl = True

42 Chapter 4. API Details

Page 47: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

CHAPTER 5

Indices and tables

• genindex

• modindex

• search

43

Page 48: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Alembic Documentation, Release 0.2.2

44 Chapter 5. Indices and tables

Page 49: Alembic Documentation · 2b1ae634e5cd_add_order_id.py 3adcc9a56557_rename_username_field.py The directory includes these directories/files: • yourproject - this is the root of

Python Module Index

aalembic.command, ??alembic.config, ??alembic.ddl, ??alembic.ddl.base, ??alembic.ddl.impl, ??alembic.ddl.mssql, ??alembic.ddl.mysql, ??alembic.ddl.postgresql, ??alembic.ddl.sqlite, ??alembic.environment, ??alembic.migration, ??alembic.operations, ??alembic.script, ??

45