Skip to content

Commit d6d3e37

Browse files
authored
feat(database): add ShouldMigrate interface (#1273)
1 parent 768273a commit d6d3e37

File tree

8 files changed

+144
-29
lines changed

8 files changed

+144
-29
lines changed

packages/database/src/Database.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@
66

77
use Tempest\Database\Builder\QueryBuilders\BuildsQuery;
88
use Tempest\Database\Config\DatabaseDialect;
9+
use UnitEnum;
910

1011
interface Database
1112
{
1213
public DatabaseDialect $dialect {
1314
get;
1415
}
1516

17+
public null|string|UnitEnum $tag {
18+
get;
19+
}
20+
1621
public function execute(BuildsQuery|Query $query): void;
1722

1823
public function getLastInsertId(): ?Id;

packages/database/src/GenericDatabase.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Tempest\Database\Exceptions\QueryException;
1616
use Tempest\Database\Transactions\TransactionManager;
1717
use Throwable;
18+
use UnitEnum;
1819

1920
final class GenericDatabase implements Database
2021
{
@@ -25,6 +26,10 @@ final class GenericDatabase implements Database
2526
get => $this->connection->config->dialect;
2627
}
2728

29+
public null|string|UnitEnum $tag {
30+
get => $this->connection->config->tag;
31+
}
32+
2833
public function __construct(
2934
private(set) readonly Connection $connection,
3035
private(set) readonly TransactionManager $transactionManager,

packages/database/src/Migrations/MigrationManager.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Tempest\Database\QueryStatements\DropTableStatement;
2222
use Tempest\Database\QueryStatements\SetForeignKeyChecksStatement;
2323
use Tempest\Database\QueryStatements\ShowTablesStatement;
24+
use Tempest\Database\ShouldMigrate;
2425
use Throwable;
2526

2627
use function Tempest\Database\query;
@@ -188,6 +189,10 @@ public function validate(): void
188189

189190
public function executeUp(MigrationInterface $migration): void
190191
{
192+
if ($migration instanceof ShouldMigrate && $migration->shouldMigrate($this->database) === false) {
193+
return;
194+
}
195+
191196
$statement = $migration->up();
192197

193198
if ($statement === null) {
@@ -237,6 +242,10 @@ public function executeUp(MigrationInterface $migration): void
237242

238243
public function executeDown(MigrationInterface $migration): void
239244
{
245+
if ($migration instanceof ShouldMigrate && $migration->shouldMigrate($this->database) === false) {
246+
return;
247+
}
248+
240249
$statement = $migration->down();
241250

242251
if ($statement === null) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Tempest\Database;
4+
5+
interface ShouldMigrate
6+
{
7+
public function shouldMigrate(Database $database): bool;
8+
}

src/Tempest/Framework/Commands/MigrateUpCommand.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
use Tempest\Database\Migrations\MigrationMigrated;
1717
use Tempest\EventBus\EventHandler;
1818

19-
use function Tempest\get;
20-
2119
#[Singleton]
2220
final class MigrateUpCommand
2321
{
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Tests\Tempest\Integration\Database\Fixtures;
4+
5+
use Tempest\Database\Database;
6+
use Tempest\Database\DatabaseMigration;
7+
use Tempest\Database\QueryStatement;
8+
use Tempest\Database\QueryStatements\CreateTableStatement;
9+
use Tempest\Database\QueryStatements\DropTableStatement;
10+
use Tempest\Database\ShouldMigrate;
11+
12+
final class MigrationForBackup implements DatabaseMigration, ShouldMigrate
13+
{
14+
public string $name = '000_backup';
15+
16+
public function shouldMigrate(Database $database): bool
17+
{
18+
return $database->tag === 'backup';
19+
}
20+
21+
public function up(): QueryStatement
22+
{
23+
return new CreateTableStatement('backup_table')->primary();
24+
}
25+
26+
public function down(): QueryStatement
27+
{
28+
return new DropTableStatement('backup_table');
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Tests\Tempest\Integration\Database\Fixtures;
4+
5+
use Tempest\Database\Database;
6+
use Tempest\Database\DatabaseMigration;
7+
use Tempest\Database\QueryStatement;
8+
use Tempest\Database\QueryStatements\CreateTableStatement;
9+
use Tempest\Database\QueryStatements\DropTableStatement;
10+
use Tempest\Database\ShouldMigrate;
11+
12+
final class MigrationForMain implements DatabaseMigration, ShouldMigrate
13+
{
14+
public string $name = '000_main';
15+
16+
public function shouldMigrate(Database $database): bool
17+
{
18+
return $database->tag === 'main';
19+
}
20+
21+
public function up(): QueryStatement
22+
{
23+
return new CreateTableStatement('main_table')->primary();
24+
}
25+
26+
public function down(): QueryStatement
27+
{
28+
return new DropTableStatement('main_table');
29+
}
30+
}

tests/Integration/Database/MultiDatabaseTest.php

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Tempest\Database\Migrations\MigrationManager;
1616
use Tests\Tempest\Fixtures\Migrations\CreatePublishersTable;
1717
use Tests\Tempest\Fixtures\Modules\Books\Models\Publisher;
18+
use Tests\Tempest\Integration\Database\Fixtures\MigrationForBackup;
19+
use Tests\Tempest\Integration\Database\Fixtures\MigrationForMain;
1820
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
1921
use Tests\Tempest\Integration\TestingDatabaseInitializer;
2022

@@ -168,18 +170,14 @@ public function test_migrate_up_command(): void
168170
->call('migrate:up --database=main')
169171
->assertSuccess();
170172

171-
$this->assertTrue(query(Migration::class)->count()->onDatabase('main')->execute() > 0);
172-
173-
$this->assertException(
174-
PDOException::class,
175-
fn () => $this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0),
176-
);
173+
$this->assertTableExists(Migration::class, 'main');
174+
$this->assertTableDoesNotExist(Migration::class, 'backup');
177175

178176
$this->console
179177
->call('migrate:up --database=backup')
180178
->assertSuccess();
181179

182-
$this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0);
180+
$this->assertTableExists(Migration::class, 'backup');
183181
}
184182

185183
public function test_migrate_fresh_command(): void
@@ -188,18 +186,14 @@ public function test_migrate_fresh_command(): void
188186
->call('migrate:fresh --database=main')
189187
->assertSuccess();
190188

191-
$this->assertTrue(query(Migration::class)->count()->onDatabase('main')->execute() > 0);
192-
193-
$this->assertException(
194-
PDOException::class,
195-
fn () => $this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0),
196-
);
189+
$this->assertTableExists(Migration::class, 'main');
190+
$this->assertTableDoesNotExist(Migration::class, 'backup');
197191

198192
$this->console
199193
->call('migrate:fresh --database=backup')
200194
->assertSuccess();
201195

202-
$this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0);
196+
$this->assertTableExists(Migration::class, 'backup');
203197
}
204198

205199
public function test_migrate_up_fresh_command(): void
@@ -208,18 +202,14 @@ public function test_migrate_up_fresh_command(): void
208202
->call('migrate:up --fresh --database=main')
209203
->assertSuccess();
210204

211-
$this->assertTrue(query(Migration::class)->count()->onDatabase('main')->execute() > 0);
212-
213-
$this->assertException(
214-
PDOException::class,
215-
fn () => $this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0),
216-
);
205+
$this->assertTableExists(Migration::class, 'main');
206+
$this->assertTableDoesNotExist(Migration::class, 'backup');
217207

218208
$this->console
219209
->call('migrate:up --fresh --database=backup')
220210
->assertSuccess();
221211

222-
$this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0);
212+
$this->assertTableExists(Migration::class, 'backup');
223213
}
224214

225215
public function test_migrate_down_command(): void
@@ -236,12 +226,8 @@ public function test_migrate_down_command(): void
236226
->call('migrate:down --database=backup')
237227
->assertSuccess();
238228

239-
$this->assertTrue(query(Migration::class)->count()->onDatabase('main')->execute() > 0);
240-
241-
$this->assertException(
242-
PDOException::class,
243-
fn () => $this->assertTrue(query(Migration::class)->count()->onDatabase('backup')->execute() > 0),
244-
);
229+
$this->assertTableExists(Migration::class, 'main');
230+
$this->assertTableDoesNotExist(Migration::class, 'backup');
245231
}
246232

247233
public function test_migrate_validate_command(): void
@@ -250,4 +236,48 @@ public function test_migrate_validate_command(): void
250236
->call('migrate:validate --database=main')
251237
->assertSuccess();
252238
}
239+
240+
public function test_should_migrate(): void
241+
{
242+
/** @var MigrationManager $migrationManager */
243+
$migrationManager = $this->container->get(MigrationManager::class);
244+
245+
$migrationManager->onDatabase('main')->executeUp(new CreateMigrationsTable());
246+
$migrationManager->onDatabase('backup')->executeUp(new CreateMigrationsTable());
247+
248+
$migrationManager->onDatabase('main')->executeUp(new MigrationForMain());
249+
$migrationManager->onDatabase('main')->executeUp(new MigrationForBackup());
250+
251+
$this->assertTableExists('main_table', 'main');
252+
$this->assertTableDoesNotExist('backup_table', 'main');
253+
254+
$migrationManager->onDatabase('backup')->executeUp(new MigrationForMain());
255+
$migrationManager->onDatabase('backup')->executeUp(new MigrationForBackup());
256+
257+
$this->assertTableExists('backup_table', 'backup');
258+
$this->assertTableDoesNotExist('main_table', 'backup');
259+
260+
$migrationManager->onDatabase('main')->executeDown(new MigrationForMain());
261+
$migrationManager->onDatabase('main')->executeDown(new MigrationForBackup());
262+
$this->assertTableDoesNotExist('main_table', 'main');
263+
$this->assertTableDoesNotExist('backup_table', 'main');
264+
265+
$migrationManager->onDatabase('backup')->executeDown(new MigrationForBackup());
266+
$migrationManager->onDatabase('backup')->executeDown(new MigrationForMain());
267+
$this->assertTableDoesNotExist('backup_table', 'backup');
268+
$this->assertTableDoesNotExist('main_table', 'backup');
269+
}
270+
271+
private function assertTableExists(string $tableName, string $onDatabase): void
272+
{
273+
$this->assertTrue(query($tableName)->count()->onDatabase($onDatabase)->execute() >= 0);
274+
}
275+
276+
private function assertTableDoesNotExist(string $tableName, string $onDatabase): void
277+
{
278+
$this->assertException(
279+
PDOException::class,
280+
fn () => query($tableName)->count()->onDatabase($onDatabase)->execute(),
281+
);
282+
}
253283
}

0 commit comments

Comments
 (0)