Skip to content

Commit

Permalink
Merge pull request #1265 from wiistriker/write-sql-meta-table-update
Browse files Browse the repository at this point in the history
  • Loading branch information
greg0ire committed Aug 4, 2022
2 parents 1daea63 + e3d3265 commit 61c6ef3
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 6 deletions.
6 changes: 5 additions & 1 deletion lib/Doctrine/Migrations/Metadata/Storage/MetadataStorage.php
Expand Up @@ -5,15 +5,19 @@
namespace Doctrine\Migrations\Metadata\Storage;

use Doctrine\Migrations\Metadata\ExecutedMigrationsList;
use Doctrine\Migrations\Query\Query;
use Doctrine\Migrations\Version\ExecutionResult;

/**
* @method iterable<Query> getSql(ExecutionResult $result);
*/
interface MetadataStorage
{
public function ensureInitialized(): void;

public function getExecutedMigrations(): ExecutedMigrationsList;

public function complete(ExecutionResult $migration): void;
public function complete(ExecutionResult $result): void;

public function reset(): void;
}
30 changes: 30 additions & 0 deletions lib/Doctrine/Migrations/Metadata/Storage/TableMetadataStorage.php
Expand Up @@ -17,6 +17,7 @@
use Doctrine\Migrations\Metadata\ExecutedMigration;
use Doctrine\Migrations\Metadata\ExecutedMigrationsList;
use Doctrine\Migrations\MigrationsRepository;
use Doctrine\Migrations\Query\Query;
use Doctrine\Migrations\Version\Comparator as MigrationsComparator;
use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\ExecutionResult;
Expand Down Expand Up @@ -145,6 +146,35 @@ public function complete(ExecutionResult $result): void
}
}

/**
* @return iterable<Query>
*/
public function getSql(ExecutionResult $result): iterable
{
yield new Query('-- Version ' . (string) $result->getVersion() . ' update table metadata');

if ($result->getDirection() === Direction::DOWN) {
yield new Query(sprintf(
'DELETE FROM %s WHERE %s = %s',
$this->configuration->getTableName(),
$this->configuration->getVersionColumnName(),
$this->connection->quote((string) $result->getVersion())
));

return;
}

yield new Query(sprintf(
'INSERT INTO %s (%s, %s, %s) VALUES (%s, %s, 0)',
$this->configuration->getTableName(),
$this->configuration->getVersionColumnName(),
$this->configuration->getExecutedAtColumnName(),
$this->configuration->getExecutionTimeColumnName(),
$this->connection->quote((string) $result->getVersion()),
$this->connection->quote(($result->getExecutedAt() ?? new DateTimeImmutable())->format('Y-m-d H:i:s'))
));
}

public function ensureInitialized(): void
{
if (! $this->isInitialized()) {
Expand Down
5 changes: 5 additions & 0 deletions lib/Doctrine/Migrations/Version/DbalExecutor.php
Expand Up @@ -25,6 +25,7 @@
use Throwable;

use function count;
use function method_exists;
use function ucfirst;

/**
Expand Down Expand Up @@ -203,6 +204,10 @@ private function executeMigration(

if (! $configuration->isDryRun()) {
$this->metadataStorage->complete($result);
} elseif (method_exists($this->metadataStorage, 'getSql')) {
foreach ($this->metadataStorage->getSql($result) as $sqlQuery) {
$this->addSql($sqlQuery);
}
}

if ($migration->isTransactional()) {
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon.dist
Expand Up @@ -44,6 +44,10 @@ parameters:
count: 1
path: tests/Doctrine/Migrations/Tests/Tools/Console/legacy-config-orm/cli-config.php

-
message: '~^Call to function method_exists\(\) with Doctrine\\Migrations\\Metadata\\Storage\\MetadataStorage and ''getSql'' will always evaluate to true\.$~'
path: lib/Doctrine/Migrations/Version/DbalExecutor.php

symfony:
console_application_loader: tests/Doctrine/Migrations/Tests/doctrine-migrations-phpstan-app.php
includes:
Expand Down
Expand Up @@ -355,4 +355,49 @@ public function testResetWithEmptySchema(): void
);
self::assertCount(0, $this->connection->fetchAllAssociative($sql));
}

public function testGetSql(): void
{
$this->storage->ensureInitialized();

$result = new ExecutionResult(new Version('2230'), Direction::UP, new DateTimeImmutable('2010-01-05 10:30:21'));

$queries = [...$this->storage->getSql($result)];

self::assertCount(2, $queries);
self::assertSame('-- Version 2230 update table metadata', $queries[0]->getStatement());
self::assertSame(sprintf(
"INSERT INTO doctrine_migration_versions (version, executed_at, execution_time) VALUES ('%s', '%s', 0)",
'2230',
'2010-01-05 10:30:21'
), $queries[1]->getStatement());

foreach ($queries as $query) {
$this->connection->executeStatement($query->getStatement());
}

$sql = sprintf(
'SELECT * FROM %s WHERE version = 2230',
$this->connection->getDatabasePlatform()->quoteIdentifier($this->config->getTableName())
);

self::assertCount(1, $this->connection->fetchAllAssociative($sql));

$result = new ExecutionResult(new Version('2230'), Direction::DOWN, new DateTimeImmutable('2010-01-05 10:30:21'));

$queries = [...$this->storage->getSql($result)];

self::assertCount(2, $queries);
self::assertSame('-- Version 2230 update table metadata', $queries[0]->getStatement());
self::assertSame(sprintf(
"DELETE FROM doctrine_migration_versions WHERE version = '%s'",
'2230'
), $queries[1]->getStatement());

foreach ($queries as $query) {
$this->connection->executeStatement($query->getStatement());
}

self::assertCount(0, $this->connection->fetchAllAssociative($sql));
}
}
4 changes: 3 additions & 1 deletion tests/Doctrine/Migrations/Tests/RollupTest.php
Expand Up @@ -56,8 +56,10 @@ public function testRollup(): void
$this->storage
->expects(self::exactly(1))
->method('complete')
->willReturnCallback(static function (ExecutionResult $result): void {
->willReturnCallback(static function (ExecutionResult $result): array {
self::assertEquals(new Version('A'), $result->getVersion());

return [];
})->with();

$this->rollup->rollup();
Expand Down
30 changes: 26 additions & 4 deletions tests/Doctrine/Migrations/Tests/Version/ExecutorTest.php
Expand Up @@ -210,6 +210,14 @@ public function testExecuteDryRun(): void
->expects(self::never())
->method('complete');

$this->metadataStorage
->expects(self::once())
->method('getSql')->willReturnCallback(static function (ExecutionResult $result): iterable {
self::assertSame(Direction::UP, $result->getDirection());

yield new Query('INSERT INTO doctrine_migration_versions (version, executed_at, execution_time) VALUE (' . $result->getVersion() . ', NOW(), 0)');
});

$this->connection
->expects(self::never())
->method('executeQuery');
Expand All @@ -230,7 +238,8 @@ public function testExecuteDryRun(): void
);

$queries = $result->getSql();
self::assertCount(2, $queries);

self::assertCount(3, $queries);
self::assertSame('SELECT 1', $queries[0]->getStatement());
self::assertSame([1], $queries[0]->getParameters());
self::assertSame([3], $queries[0]->getTypes());
Expand All @@ -239,6 +248,10 @@ public function testExecuteDryRun(): void
self::assertSame([], $queries[1]->getParameters());
self::assertSame([], $queries[1]->getTypes());

self::assertSame('INSERT INTO doctrine_migration_versions (version, executed_at, execution_time) VALUE (' . $result->getVersion() . ', NOW(), 0)', $queries[2]->getStatement());
self::assertSame([], $queries[2]->getParameters());
self::assertSame([], $queries[2]->getTypes());

self::assertNotNull($result->getTime());
self::assertSame(State::NONE, $result->getState());
self::assertTrue($this->migration->preUpExecuted);
Expand Down Expand Up @@ -501,9 +514,18 @@ public function executeDownShouldAppendDescriptionWhenItIsNotEmpty(): void

protected function setUp(): void
{
$this->metadataStorage = $this->createMock(MetadataStorage::class);
$this->connection = $this->createMock(Connection::class);
$driverConnection = $this->createStub(DriverConnection::class);
// add getSql to mock until method will be added to MetadataStorage interface
$this->metadataStorage = $this->getMockBuilder(MetadataStorage::class)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->onlyMethods(['ensureInitialized', 'getExecutedMigrations', 'complete', 'reset'])
->addMethods(['getSql'])
->getMock();

$this->connection = $this->createMock(Connection::class);
$driverConnection = $this->createStub(DriverConnection::class);
$this->connection->method('getWrappedConnection')->willReturn($driverConnection);
$this->schemaDiffProvider = $this->createMock(SchemaDiffProvider::class);
$this->parameterFormatter = $this->createMock(ParameterFormatter::class);
Expand Down

0 comments on commit 61c6ef3

Please sign in to comment.