update documentation
This commit is contained in:
parent
03eb309b67
commit
431d22be61
@ -1,8 +1,8 @@
|
||||
.. _changeset-system:
|
||||
|
||||
**********************
|
||||
Database changeset API
|
||||
**********************
|
||||
******************
|
||||
Database changeset
|
||||
******************
|
||||
|
||||
.. currentmodule:: migrate.changeset
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
Download
|
||||
--------
|
||||
|
||||
SQLAlchemy-Migrate builds on SQLAlchemy_, so you should install that
|
||||
first.
|
||||
|
||||
You can get the latest version of SQLAlchemy Migrate from the
|
||||
`project's download page`_, the `cheese shop`_, or via easy_install_::
|
||||
|
||||
@ -38,5 +35,8 @@ To get the latest trunk::
|
||||
|
||||
Patches should be submitted to the `issue tracker`_.
|
||||
|
||||
We use `buildbot`_ to help us run tests on all databases that migrate supports.
|
||||
|
||||
.. _subversion: http://subversion.tigris.org/
|
||||
.. _issue tracker: http://code.google.com/p/sqlalchemy-migrate/issues/list
|
||||
.. _buildbot: http://buildbot.fubar.si
|
||||
|
@ -24,9 +24,12 @@
|
||||
project`_. During the hosting change the project was renamed to
|
||||
SQLAlchemy Migrate.
|
||||
|
||||
Currently, sqlalchemy-migrate supports Python versions from 2.4 to 2.6.
|
||||
SQLAlchemy >=0.5 is supported only.
|
||||
|
||||
.. warning::
|
||||
|
||||
**0.5.5** release breaks backward compatability, please read :ref:`changelog <backwards-055>` for more info.
|
||||
Version **0.5.5** breaks backward compatability, please read :ref:`changelog <backwards-055>` for more info.
|
||||
|
||||
Download and Development of SQLAlchemy Migrate
|
||||
----------------------------------------------
|
||||
@ -41,7 +44,7 @@ Documentation
|
||||
SQLAlchemy is split into two parts, database schema versioning and
|
||||
database changeset management. This is represented by two python
|
||||
packages :mod:`migrate.versioning` and :mod:`migrate.changeset`. The
|
||||
versioning API is available as the :command:`migrate` command.
|
||||
versioning API is available as the :ref:`migrate <command-line-usage>` command.
|
||||
|
||||
.. toctree::
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
SQLAlchemy migrate tools
|
||||
========================
|
||||
|
||||
The most commonly used tool is the :command:`migrate` script that is
|
||||
discussed in depth in the :ref:`Database schema versioning
|
||||
<versioning-system>` part of the documentation.
|
||||
The most commonly used tool is the :ref:`migrate <command-line-usage>`.
|
||||
|
||||
.. index:: repository migration
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
.. _versioning-system:
|
||||
.. currentmodule:: migrate.versioning
|
||||
.. highlight:: bash
|
||||
|
||||
**************************
|
||||
Database schema versioning
|
||||
**************************
|
||||
***********************************
|
||||
Database schema versioning workflow
|
||||
***********************************
|
||||
|
||||
SQLAlchemy migrate provides the :mod:`migrate.versioning` API that is
|
||||
also available as the :command:`migrate` command.
|
||||
also available as the :ref:`migrate <command-line-usage>` command.
|
||||
|
||||
Purpose of this package is frontend for migrations. It provides commands
|
||||
to manage migrate repository and database selection aswell as script versioning.
|
||||
|
||||
.. program:: migrate
|
||||
|
||||
Project Setup
|
||||
=============
|
||||
@ -28,16 +32,16 @@ repository we're working with.
|
||||
All work with repositories is done using the migrate command. Let's
|
||||
create our project's repository::
|
||||
|
||||
% migrate create my_repository "Example project"
|
||||
$ migrate create my_repository "Example project"
|
||||
|
||||
This creates an initially empty repository in the current directory at
|
||||
my_repository/ named Example project. The repository directory
|
||||
This creates an initially empty repository relative to current directory at
|
||||
my_repository/ named `Example project`. The repository directory
|
||||
contains a sub directory versions that will store the schema versions,
|
||||
a configuration file :file:`migrate.cfg` that contains
|
||||
:ref:`repository configuration <repository_configuration>`, a
|
||||
:file:`README` file containing information that the directory is an
|
||||
sqlalchemy-migrate repository and a script :file:`manage.py` that has
|
||||
the same functionality as the :command:`migrate` command but is
|
||||
sqlalchemy-migrate repository and a script :ref:`manage.py <project_management_script>`
|
||||
that has the same functionality as the :ref:`migrate <command-line-usage>` command but is
|
||||
preconfigured with the repository.
|
||||
|
||||
Version-control a database
|
||||
@ -56,7 +60,7 @@ The database is specified as a `SQLAlchemy database url`_.
|
||||
|
||||
::
|
||||
|
||||
% python my_repository/manage.py version_control sqlite:///project.db
|
||||
$ python my_repository/manage.py version_control sqlite:///project.db
|
||||
|
||||
We can have any number of databases under this repository's version
|
||||
control.
|
||||
@ -65,7 +69,7 @@ Each schema has a version that SQLAlchemy Migrate manages. Each change
|
||||
script applied to the database increments this version number. You can
|
||||
see a database's current version::
|
||||
|
||||
% python my_repository/manage.py db_version sqlite:///project.db
|
||||
$ python my_repository/manage.py db_version sqlite:///project.db
|
||||
0
|
||||
|
||||
A freshly versioned database begins at version 0 by default. This
|
||||
@ -77,7 +81,7 @@ and applying change scripts changes the database's version number.
|
||||
Similarly, we can also see the latest version available in a
|
||||
repository with the command::
|
||||
|
||||
% python my_repository/manage.py version
|
||||
$ python my_repository/manage.py version
|
||||
0
|
||||
|
||||
We've entered no changes so far, so our repository cannot upgrade a
|
||||
@ -93,8 +97,8 @@ path - typing them each time is tedious. We can create a script for
|
||||
our project that remembers the database and repository we're using,
|
||||
and use it to perform commands::
|
||||
|
||||
% migrate manage manage.py --repository=my_repository --url=sqlite:///project.db
|
||||
% python manage.py db_version
|
||||
$ migrate manage manage.py --repository=my_repository --url=sqlite:///project.db
|
||||
$ python manage.py db_version
|
||||
0
|
||||
|
||||
The script manage.py was created. All commands we perform with it are
|
||||
@ -117,17 +121,19 @@ helps ensure multiple databases you're working with are consistent.
|
||||
Create a change script
|
||||
----------------------
|
||||
|
||||
Our first change script will create a simple table::
|
||||
Our first change script will create a simple table
|
||||
|
||||
account = Table('account',meta,
|
||||
Column('id',Integer,primary_key=True),
|
||||
Column('login',String(40)),
|
||||
Column('passwd',String(40)),
|
||||
)
|
||||
.. code-block:: python
|
||||
|
||||
account = Table('account', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('login', String(40)),
|
||||
Column('passwd', String(40)),
|
||||
)
|
||||
|
||||
This table should be created in a change script. Let's create one::
|
||||
|
||||
% python manage.py script "Add account table"
|
||||
$ python manage.py script "Add account table"
|
||||
|
||||
This creates an empty change script at
|
||||
:file:`my_repository/versions/001_Add_account_table.py`. Next, we'll
|
||||
@ -137,34 +143,38 @@ Edit the change script
|
||||
----------------------
|
||||
|
||||
Our change script defines two functions, currently empty:
|
||||
``upgrade()`` and ``downgrade()``. We'll fill those in::
|
||||
:func:`upgrade`` and :func:`downgrade`. We'll fill those in
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from sqlalchemy import *
|
||||
from migrate import *
|
||||
|
||||
meta = MetaData(migrate_engine)
|
||||
meta = MetaData()
|
||||
account = Table('account', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('login', String(40)),
|
||||
Column('passwd', String(40)),
|
||||
)
|
||||
|
||||
def upgrade():
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind(migrate_engine)
|
||||
account.create()
|
||||
|
||||
def downgrade():
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind(migrate_engine)
|
||||
account.drop()
|
||||
|
||||
As you might have guessed, upgrade() upgrades the database to the next
|
||||
As you might have guessed, :func:`upgrade` upgrades the database to the next
|
||||
version. This function should contain the changes we want to perform;
|
||||
here, we're creating a table. downgrade() should reverse changes made
|
||||
by upgrade(). You'll need to write both functions for every change
|
||||
script. (Well, you don't *have* to write downgrade(), but you won't be
|
||||
here, we're creating a table. :func:`downgrade` should reverse changes made
|
||||
by :func:`upgrade`. You'll need to write both functions for every change
|
||||
script. (Well, you don't *have* to write downgrade, but you won't be
|
||||
able to revert to an older version of the database or test your
|
||||
scripts without it.)
|
||||
|
||||
``from migrate import *`` imports a special SQLAlchemy engine named
|
||||
'migrate_engine'. You should use this in your change scripts, rather
|
||||
As you can see, **migrate_engine** is passed to both functions.
|
||||
You should use this in your change scripts, rather
|
||||
than creating your own engine.
|
||||
|
||||
You should be very careful about importing files from the rest of your
|
||||
@ -175,17 +185,15 @@ Test the change script
|
||||
------------------------
|
||||
|
||||
Change scripts should be tested before they are committed. Testing a
|
||||
script will run its upgrade() and downgrade() functions on a specified
|
||||
script will run its :func:`upgrade` and :func:`downgrade` functions on a specified
|
||||
database; you can ensure the script runs without error. You should be
|
||||
testing on a test database - if something goes wrong here, you'll need
|
||||
to correct it by hand. If the test is successful, the database should
|
||||
appear unchanged after upgrade() and downgrade() run.
|
||||
|
||||
To test the script:
|
||||
To test the script::
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
% python manage.py test
|
||||
$ python manage.py test
|
||||
Upgrading... done
|
||||
Downgrading... done
|
||||
Success
|
||||
@ -195,28 +203,31 @@ specified in manage.py) without any errors.
|
||||
|
||||
Our repository's version now is::
|
||||
|
||||
% python manage.py version
|
||||
$ python manage.py version
|
||||
1
|
||||
|
||||
.. warning::
|
||||
|
||||
test command exectues actual script, be sure you are NOT doing this on production database.
|
||||
|
||||
|
||||
Upgrade the database
|
||||
--------------------
|
||||
|
||||
Now, we can apply this change script to our database::
|
||||
|
||||
% python manage.py upgrade
|
||||
$ python manage.py upgrade
|
||||
0 -> 1... done
|
||||
|
||||
This upgrades the database (``sqlite:///project.db``, as specified
|
||||
when we created manage.py above) to the latest available version. (We
|
||||
could also specify a version number if we wished, using the --version
|
||||
could also specify a version number if we wished, using the ``--version``
|
||||
option.) We can see the database's version number has changed, and our
|
||||
table has been created:
|
||||
table has been created::
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
% python manage.py db_version
|
||||
$ python manage.py db_version
|
||||
1
|
||||
% sqlite3 project.db
|
||||
$ sqlite3 project.db
|
||||
sqlite> .tables
|
||||
account migrate_version
|
||||
|
||||
@ -243,54 +254,58 @@ every time, despite any changes to your app's source code. You don't
|
||||
want your change scripts' behavior changing when your source code
|
||||
does.
|
||||
|
||||
Consider the following example of what can go wrong (i.e. what NOT to
|
||||
do):
|
||||
**Consider the following example of what can go wrong (i.e. what NOT to
|
||||
do)**:
|
||||
|
||||
Your application defines a table in the model.py file:
|
||||
|
||||
::
|
||||
.. code-block:: python
|
||||
|
||||
from sqlalchemy import *
|
||||
|
||||
meta = MetaData()
|
||||
table = Table('mytable',meta,
|
||||
Column('id',Integer,primary_key=True),
|
||||
table = Table('mytable', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
)
|
||||
|
||||
...and uses this file to create a table in a change script:
|
||||
... and uses this file to create a table in a change script:
|
||||
|
||||
::
|
||||
.. code-block:: python
|
||||
|
||||
from sqlalchemy import *
|
||||
from migrate import *
|
||||
import model
|
||||
model.meta.connect(migrate_engine)
|
||||
|
||||
def upgrade():
|
||||
model.table.create()
|
||||
def downgrade():
|
||||
def upgrade(migrate_engine):
|
||||
model.meta.bind(migrate_engine)
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
model.meta.bind(migrate_engine)
|
||||
model.table.drop()
|
||||
|
||||
This runs successfully the first time. But what happens if we change
|
||||
the table definition?
|
||||
|
||||
::
|
||||
.. code-block:: python
|
||||
|
||||
table = Table('mytable',meta,
|
||||
Column('id',Integer,primary_key=True),
|
||||
Column('data',String(42)),
|
||||
table = Table('mytable', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('data', String(42)),
|
||||
)
|
||||
|
||||
We'll create a new column with a matching change script::
|
||||
We'll create a new column with a matching change script
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from sqlalchemy import *
|
||||
from migrate import *
|
||||
import model
|
||||
model.meta.connect(migrate_engine)
|
||||
|
||||
def upgrade():
|
||||
def upgrade(migrate_engine):
|
||||
model.meta.bind(migrate_engine)
|
||||
model.table.data.create()
|
||||
def downgrade():
|
||||
def downgrade(migrate_engine):
|
||||
model.meta.bind(migrate_engine)
|
||||
model.table.data.drop()
|
||||
|
||||
This appears to run fine when upgrading an existing database - but the
|
||||
@ -309,7 +324,9 @@ Writing for a specific database
|
||||
Sometimes you need to write code for a specific database. Migrate
|
||||
scripts can run under any database, however - the engine you're given
|
||||
might belong to any database. Use engine.name to get the name of the
|
||||
database you're working with::
|
||||
database you're working with
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> from sqlalchemy import *
|
||||
>>> from migrate import *
|
||||
@ -322,11 +339,13 @@ Writings .sql scripts
|
||||
---------------------
|
||||
|
||||
You might prefer to write your change scripts in SQL, as .sql files,
|
||||
rather than as Python scripts. SQLAlchemy-migrate can work with that::
|
||||
rather than as Python scripts. SQLAlchemy-migrate can work with that
|
||||
|
||||
% python manage.py version
|
||||
.. code-block:: python
|
||||
|
||||
$ python manage.py version
|
||||
1
|
||||
% python manage.py script_sql postgres
|
||||
$ python manage.py script_sql postgres
|
||||
|
||||
This creates two scripts
|
||||
:file:`my_repository/versions/002_postgresql_upgrade.sql` and
|
||||
@ -338,27 +357,29 @@ database defined by SQLAlchemy may be used here - ex. sqlite,
|
||||
postgres, oracle, mysql...
|
||||
|
||||
|
||||
.. _command-line-usage:
|
||||
|
||||
Command line usage
|
||||
==================
|
||||
|
||||
.. currentmodule:: migrate.versioning.shell
|
||||
|
||||
:command:`migrate` command is used for API interface. For list of commands and help use
|
||||
:command:`migrate` command is used for API interface. For list of commands and help use::
|
||||
|
||||
::
|
||||
$ migrate --help
|
||||
|
||||
migrate --help
|
||||
|
||||
:program:`migrate` command uses :func:`migrate.versioning.shell.main` function.
|
||||
:program:`migrate` command exectues :func:`main` function.
|
||||
For ease of usage, generate your own :ref:`project management script <project_management_script>`,
|
||||
which calls :func:`shell.main` function with keywords arguments.
|
||||
You may want to specify `url` and `repository` arguments which almost all API functions require as positional arguments.
|
||||
which calls :func:`main` function with keywords arguments.
|
||||
You may want to specify `url` and `repository` arguments which almost all API functions require.
|
||||
|
||||
If api command looks like::
|
||||
|
||||
migrate downgrade URL REPOSITORY VERSION [--preview_sql|--preview_py]
|
||||
$ migrate downgrade URL REPOSITORY VERSION [--preview_sql|--preview_py]
|
||||
|
||||
and you have a project management script that looks like::
|
||||
and you have a project management script that looks like
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from migrate.versioning.shell import main
|
||||
|
||||
@ -366,7 +387,7 @@ and you have a project management script that looks like::
|
||||
|
||||
you have first two slots filed, and command line usage would look like::
|
||||
|
||||
# downgrade to version 2 and preview Python file
|
||||
# preview Python script
|
||||
migrate downgrade 2 --preview_py
|
||||
|
||||
# downgrade to version 2
|
||||
@ -376,7 +397,7 @@ you have first two slots filed, and command line usage would look like::
|
||||
Command line parsing refactored: positional parameters usage
|
||||
|
||||
Whole command line parsing was rewriten from scratch with use of OptionParser.
|
||||
Options passed as kwargs to :func:`migrate.versioning.shell.main` are now parsed correctly.
|
||||
Options passed as kwargs to :func:`~migrate.versioning.shell.main` are now parsed correctly.
|
||||
Options are passed to commands in the following priority (starting from highest):
|
||||
|
||||
- optional (given by ``--some_option`` in commandline)
|
||||
@ -387,11 +408,11 @@ Options are passed to commands in the following priority (starting from highest)
|
||||
Python API
|
||||
==========
|
||||
|
||||
.. currentmodule:: migrate.versioning
|
||||
.. currentmodule:: migrate.versioning.api
|
||||
|
||||
All commands available from the command line are also available for
|
||||
your Python scripts by importing :mod:`migrate.versioning`. See the
|
||||
:mod:`migrate.versioning` documentation for a list of functions;
|
||||
your Python scripts by importing :mod:`migrate.versioning.api`. See the
|
||||
:mod:`migrate.versioning.api` documentation for a list of functions;
|
||||
function names match equivalent shell commands. You can use this to
|
||||
help integrate SQLAlchemy Migrate with your existing update process.
|
||||
|
||||
@ -399,12 +420,14 @@ For example, the following commands are similar:
|
||||
|
||||
*From the command line*::
|
||||
|
||||
% migrate help help
|
||||
$ migrate help help
|
||||
/usr/bin/migrate help COMMAND
|
||||
|
||||
Displays help on a given command.
|
||||
|
||||
*From Python*::
|
||||
*From Python*
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import migrate.versioning.api
|
||||
migrate.versioning.api.help('help')
|
||||
@ -469,4 +492,4 @@ currently:
|
||||
successfully during a commit, or the entire commit will fail. List
|
||||
the databases your application will actually be using to ensure your
|
||||
updates to that database work properly. This must be a list;
|
||||
example: `['postgres','sqlite']`
|
||||
example: `['postgres', 'sqlite']`
|
||||
|
@ -137,7 +137,10 @@ class PythonScript(base.BaseScript):
|
||||
funcname = base.operations[op]
|
||||
|
||||
func = self._func(funcname)
|
||||
func(engine)
|
||||
try:
|
||||
func(engine)
|
||||
except TypeError:
|
||||
print "upgrade/downgrade functions must accept one parameter (migrate_engine)"
|
||||
|
||||
@property
|
||||
def module(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user