Skip to content

Commit

Permalink
Implement all or nothing transaction strategy for migrations.
Browse files Browse the repository at this point in the history
  • Loading branch information
jwage committed May 17, 2018
1 parent a86f9ec commit 146e747
Show file tree
Hide file tree
Showing 31 changed files with 750 additions and 176 deletions.
1 change: 1 addition & 0 deletions docs/en/reference/custom_configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ code that would looks like the following:
$configuration->setMigrationsDirectory('/path/to/project/src/App/Migrations');
$configuration->setMigrationsNamespace('App/Migrations');
$configuration->registerMigrationsFromDirectory('/path/to/project/src/App/Migrations');
$configuration->setAllOrNothing(true);
// My command that extends Doctrine\DBAL\Migrations\Tools\Console\Command\AbstractCommand
$command->setMigrationConfiguration($configuration);
3 changes: 3 additions & 0 deletions docs/en/reference/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ file like the following:
<migrations-directory>/path/to/migrations/classes/DoctrineMigrations</migrations-directory>
<all-or-nothing>1</all-or-nothing>
</doctrine-migrations>
Of course you could do the same thing with a *configuration.yml* file:
Expand All @@ -82,6 +84,7 @@ Of course you could do the same thing with a *configuration.yml* file:
column_name: version
executed_at_column_name: executed_at
migrations_directory: /path/to/migrations/classes/DoctrineMigrations
all_or_nothing: true
With the above example, the migrations tool will search the ``migrations_directory``
recursively for files that begin with ``Version`` followed one to 255 characters
Expand Down
79 changes: 74 additions & 5 deletions docs/en/reference/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ commands to our `Doctrine Command Line Interface <http://doctrine-orm.readthedoc
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand()
));
Additionally you have to make sure the 'db' and 'dialog' Helpers are added to your Symfony
Additionally you have to make sure the ``db`` and ``dialog`` Helpers are added to your Symfony
Console HelperSet.

.. code-block:: php
Expand Down Expand Up @@ -185,18 +185,87 @@ the migrations are executed in the correct order.
While you *can* use custom filenames, it's probably a good idea to let Doctrine
:doc:`generate migration files </reference/generating_migrations>` for you.


And if you want to specify each migration manually in YAML you can:

.. code-block:: yaml
table_name: doctrine_migration_versions
migrations_directory: /path/to/migrations/classes/DoctrineMigrations
migrations:
migration1:
version: 20100704000000
class: DoctrineMigrations\NewMigration
migration1:
version: 20100704000000
class: DoctrineMigrations\NewMigration
If you specify your own migration classes (like `DoctrineMigrations\NewMigration` in the previous
example) you will need an autoloader unless all those classes begin with the prefix Version*,
for example path/to/migrations/classes/VersionNewMigration.php.

All or Nothing Migrations
~~~~~~~~~~~~~~~~~~~~~~~~~

If you want your migrations to be all or nothing then you can configure your migrations behave that way.
This means when you executed multiple migrations in a row, the whole migration will be wrapped
in a single migration and if one of the migrations fails, the transaction will be rolled back.

.. note::

This only works if the database connection you are using supports transactional DDL statements.

.. configuration-block::

.. code-block:: php
$configuration = new Configuration($connection);
$configuration->setAllOrNothing(true);
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-migrations xmlns="http://doctrine-project.org/schemas/migrations/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration
http://doctrine-project.org/schemas/migrations/configuration.xsd">
<name>Doctrine Sandbox Migrations</name>
<migrations-namespace>DoctrineMigrations</migrations-namespace>
<table name="doctrine_migration_versions" />
<migrations-directory>/path/to/migrations/classes/DoctrineMigrations</migrations-directory>
<all-or-nothing>true</all-or-nothing>
</doctrine-migrations>
.. code-block:: yaml
name: Doctrine Sandbox Migrations
migrations_namespace: DoctrineMigrations
table_name: doctrine_migration_versions
migrations_directory: /path/to/migrations/classes/DoctrineMigrations
all_or_nothing: true
.. code-block:: json
{
"name" : "Doctrine Sandbox Migrations",
"migrations_namespace" : "DoctrineMigrations",
"table_name" : "doctrine_migration_versions",
"migrations_directory" : "/path/to/migrations/classes/DoctrineMigrations",
"all_or_nothing" : true
}
You can also optionally use the ``--all-or-nothing`` option from the command line to enable or disable
the feature for a specific migration run:

.. code-block:: bash
$ ./doctrine migrations:migrate --all-or-nothing
Or if you have it enabled in your configuration setup and you want to disable it for a migration:

.. code-block:: bash
$ ./doctrine migrations:migrate --all-or-nothing=0
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ abstract class AbstractFileConfiguration extends Configuration
'migrations_directory',
'migrations',
'custom_template',
'all_or_nothing',
];

/** @var string */
Expand Down Expand Up @@ -113,11 +114,15 @@ protected function setConfiguration(array $config) : void
$this->loadMigrations($config['migrations']);
}

if (! isset($config['custom_template'])) {
if (isset($config['custom_template'])) {
$this->setCustomTemplate($config['custom_template']);
}

if (! isset($config['all_or_nothing'])) {
return;
}

$this->setCustomTemplate($config['custom_template']);
$this->setAllOrNothing($config['all_or_nothing']);
}

protected function getDirectoryRelativeToFile(string $file, string $input) : string
Expand Down
13 changes: 13 additions & 0 deletions lib/Doctrine/Migrations/Configuration/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class Configuration
/** @var bool */
private $isDryRun = false;

/** @var bool */
private $allOrNothing = false;

/** @var Connection */
private $connection;

Expand Down Expand Up @@ -289,6 +292,16 @@ public function isDryRun() : bool
return $this->isDryRun;
}

public function setAllOrNothing(bool $allOrNothing) : void
{
$this->allOrNothing = $allOrNothing;
}

public function isAllOrNothing() : bool
{
return $this->allOrNothing;
}

public function isMigrationTableCreated() : bool
{
return $this->getDependencyFactory()->getMigrationTableStatus()->isCreated();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
</xs:simpleType>
</xs:element>
<xs:element type="xs:string" name="migrations-directory" minOccurs="0" maxOccurs="1"/>
<xs:element type="xs:boolean" name="all-or-nothing" minOccurs="0" maxOccurs="1"/>
<xs:element name="migrations" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
Expand Down
13 changes: 12 additions & 1 deletion lib/Doctrine/Migrations/Configuration/XmlConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Doctrine\Migrations\Configuration;

use Doctrine\Migrations\Configuration\Exception\XmlNotValid;
use Doctrine\Migrations\Tools\BooleanStringFormatter;
use DOMDocument;
use const DIRECTORY_SEPARATOR;
use const LIBXML_NOCDATA;
Expand Down Expand Up @@ -62,7 +63,17 @@ protected function doLoad(string $file) : void
}

if (isset($xml->{'migrations-directory'})) {
$config['migrations_directory'] = $this->getDirectoryRelativeToFile($file, (string) $xml->{'migrations-directory'});
$config['migrations_directory'] = $this->getDirectoryRelativeToFile(
$file,
(string) $xml->{'migrations-directory'}
);
}

if (isset($xml->{'all-or-nothing'})) {
$config['all_or_nothing'] = BooleanStringFormatter::toBoolean(
(string) $xml->{'all-or-nothing'},
false
);
}

if (isset($xml->migrations->migration)) {
Expand Down
Loading

0 comments on commit 146e747

Please sign in to comment.