Like diff but for PostgreSQL schemas
Go to file
2017-03-19 16:56:51 +11:00
docs docs, 1.0 version bump 2017-03-19 16:56:51 +11:00
migra return empty string for empty migrations 2017-03-19 16:55:24 +11:00
tests return empty string for empty migrations 2017-03-19 16:55:24 +11:00
.gitignore docs, 1.0 version bump 2017-03-19 16:56:51 +11:00
LICENSE initial commit 2016-07-25 16:38:42 +12:00
Makefile initial commit 2016-07-25 16:38:42 +12:00
README.rst docs, 1.0 version bump 2017-03-19 16:56:51 +11:00
requirements-dev.txt docs, 1.0 version bump 2017-03-19 16:56:51 +11:00
requirements.txt initial commit 2016-07-25 16:38:42 +12:00
setup.py docs, 1.0 version bump 2017-03-19 16:56:51 +11:00
tox.ini support EMPTY parameter 2017-02-05 22:27:16 +11:00

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

migra: PostgreSQL migrations made almost painless
=================================================

Schema migrations are without doubt the most cumbersome and annoying part of working with SQL databases. So much so that some people think that schemas themselves are bad!

But schemas are actually good. Enforcing data consistency and structure is a good thing. Its the migration tooling that is bad, because its harder to use than it should be. ``migra`` is an attempt to change that, and make migrations easy, safe, and reliable instead of something to dread.

**Migra supports PostgreSQL >= 9.4.** Known issues exist with earlier versions.

Full documentation
------------------

Official documentation is at `migra.readthedocs.io <https://csvx.readthedocs.io/en/latest/>`_

How it Works
------------

Think of ``migra`` as a diff tool for schemas. Suppose database A and database B have similar but slightly different schemas. `migra` will detect the differences and output the SQL needed to transform A to B.

This includes changes to tables, views, functions, indexes, constraints, enums, sequences, and installed extensions.

You can use ``migra`` as a library to build your own migration scripts, tools, etc. Installing migra also installs the ``migra`` command, so you can use it as follows:

.. code-block:: shell

    $ migra postgresql:///a postgresql:///b
    alter table "public"."products" add column newcolumn text;

    alter table "public"."products" add constraint "x" CHECK ((price > (0)::numeric));

If *b* is the target schema, then a new column and constraint needs to be applied to *a* to make it match *b*'s schema. Once we've reviewed the autogenerated SQL and we're happy with it, we can apply these changes as easily as:

.. code-block:: shell

    $ migra --unsafe postgresql:///a postgresql:///b > migration_script.sql
    # Then after careful review (obviously)...
    $ psql a --single-transaction -f migration_script.sql

Migration complete!


IMPORTANT: Practice safe migrations
-----------------------------------

**Migrations can never be fully automatic**. As noted above **ALWAYS REVIEW MIGRATION SCRIPTS CAREFULLY, ESPECIALLY WHEN DROPPING TABLES IS INVOLVED**.

Best practice is to run your migrations against a copy of your production database first. This helps verify correctness and spot any performance issues before they cause interruptions and downtime on your production database.

`migra` will deliberately throw an error if any generated statements feature the word "drop". This safety feature is by no means idiot-proof, but might prevent a few obvious blunders.

If you want to generate "drop ..." statements, you need to use the ``--unsafe`` flag if using the command, or if using the python package directly, ``set_safety(`` to false on your `Migration` object.


Python Code
-----------

Here's how the migra command is implemented under the hood (with a few irrelevant lines removed).

As you can see, it's pretty simple (`S` here is a context manager that creates a database session from a database URL).

.. code-block:: python

    from migra import Migration
    from sqlbag import S

    with S(args.dburl_from) as s0, S(args.dburl_target) as s1:
        m = Migration(s0, s1)

        if args.unsafe:
            m.set_safety(False)

        m.add_all_changes()
        print(m.sql)

Here the code just opens connections to both databases for the Migration object to analyse. ``m.add_all_changes()`` generates the SQL statements for the changes required, and adds to the migration object's list of pending changes. The necessary SQL is now available as a property.


Documentation
-------------

`migra` is in early alpha and documentation is scarce so far. We are working on remedying this. Watch this space.


Features and Limitations
------------------------

``migra`` plays nicely with extensions. Schema contents belonging to extensions will be ignored and left to the extension to manage.

Only SQL/PLPGSQL functions are confirmed to work so far. ``migra`` ignores functions that use other languages.


Installation
------------

Assuming you have `pip <https://pip.pypa.io>`_ installed, all you need to do is install as follows:

.. code-block:: shell

    $ pip install migra

If you don't have psycopg2 (the PostgreSQL driver) installed yet, you can install this at the same time with:

.. code-block:: shell

    $ pip install migra[pg]