Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Issue39/db migration #371

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions app/db/migrate/0_drop_all_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
drop procedure if exists dropAllTables;

delimiter //
create procedure dropAllTables()
begin
declare tableName varchar(255);
declare isDone int default 0;
declare tableNameCursor cursor for
select TABLE_NAME
from `information_schema`.tables
where table_schema = database()
and table_type = 'BASE TABLE';
declare continue handler for sqlstate '02000' set isDone = 1;
open tableNameCursor;
repeat
fetch tableNameCursor into tableName;
if not isDone then
set @sql = CONCAT('DROP TABLE ', tableName);
prepare stmt from @sql;
execute stmt;
end if;
until isDone end repeat;
close tableNameCursor;
end
//
delimiter ;

call dropAllTables;

drop procedure if exists dropAllTables;
7 changes: 7 additions & 0 deletions app/db/migrate/20211010160000_create_tick_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE db_migrate_tick
(
tick BIGINT NOT NULL default 0 PRIMARY KEY
);

INSERT INTO db_migrate_tick (tick)
VALUES (0);
67 changes: 67 additions & 0 deletions app/src/Model/DbSchemaUpdateModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);

namespace Fc2blog\Model;

use DirectoryIterator;
use InvalidArgumentException;
use PDO;

class DbSchemaUpdateModel
{
public $pdo;
const MIGRATE_SQL_DIR = __DIR__ . "/../../db/migrate/";

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}

public function getMigrateSqlList($gth_tick): array
{
$dir = new DirectoryIterator(static::MIGRATE_SQL_DIR);

$migrate_list = [];
foreach ($dir as $row) {
if (
$row->isFile() &&
$row->getExtension() === "sql" &&
$this->getTickStringFromFileName($row->getFilename()) > $gth_tick

) {
$migrate_list[$this->getTickStringFromFileName($row->getFilename())] = $row->getFilename();
}
}

ksort($migrate_list);

return $migrate_list;
}

public function getExistsTables(): array
{
$stmt = $this->pdo->prepare("SHOW TABLES");
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
}

public function getNowTick(): int
{
$stmt = $this->pdo->prepare("SELECT tick FROM db_migrate_tick ORDER BY tick DESC");
$stmt->execute();
return $stmt->fetch(PDO::FETCH_COLUMN, 0);
}

public function getTickStringFromFileName(string $file_name): int
{
if (
!preg_match("/\A([0-9]+).*.sql\z/u", $file_name, $_) &&
!isset($_[1])
) {
throw new InvalidArgumentException("invalid filename");
}

return (int)$_[1];
}

}
1 change: 1 addition & 0 deletions app/src/Model/PDOConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static function createConnection(): PDO
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
// PDO::MYSQL_ATTR_MULTI_STATEMENTS => false // TBD
]
);
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/Model/SystemUpdateModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ public static function updateSystemByUrl(string $zip_url)

try {
static::updateSystemByLocalZip($zip_path);
// TODO issue39 migrate db

} finally {
@unlink($zip_path);
}
Expand Down
113 changes: 113 additions & 0 deletions app/src/Service/MigrationService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

namespace Fc2blog\Service;

use Exception;
use PDO;

// WIP....
class MigrationService
{
public $pdo;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}

public function migrateToLatest(): MigrationResult
{
// get latest tick
$latest_tick = 99999;
return $this->migrateToTick($latest_tick);
}

// 特定のバージョンまで移動するタスクをどうするか…
public function migrateToTick(string $tick): MigrationResult
{
try {
// get now tick


// get apply migrationTask list
/** @var MigrationTask[] $migration_task_list */
$migration_task_list = []; // getTaskList($from, $to);

// create transaction
$this->pdo->beginTransaction();

// Disable FK consistent check?

// consume task list
foreach ($migration_task_list as $migration_task) {
/** @var MigrationTask $task */
$task = require $migration_task;
if (!$task->migrate($this->pdo)) {
throw new Exception("migration failed in {$task->name}");
}
}

// Enable FK consistent check?

// commit transaction
$this->pdo->commit();

} catch (Exception $e) {

if ($this->pdo->inTransaction()) {
$this->pdo->rollBack();
}

return new MigrationResult(
false,
$e->getMessage(),
$e
);
}
return new MigrationResult(
true,
"success",
null
);
}


}

class MigrationResult
{
public $isSuccess;
public $message;
public $exception;

public function __construct(
bool $isSuccess,
string $message,
?Exception $e
)
{
$this->isSuccess = $isSuccess;
$this->message = $message;
$this->exception = $e;
}
}

class MigrationTask
{
public $name; // ???
public $tick; // ??? tick番号をココに入れる?

public function migrate(PDO $pdo): bool
{
try {
// ALTER, CREATE, DROP...

// MOVE DL DIR CREATE? change permission?

} catch (\Exception $e) {
throw $e;
}
return true;
}
}

60 changes: 60 additions & 0 deletions tests/App/Model/DbSchemaUpdateModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);

namespace Fc2blog\Tests\App\Model;

use Fc2blog\Model\DbSchemaUpdateModel;
use Fc2blog\Model\PDOConnection;
use PHPUnit\Framework\TestCase;

class DbSchemaUpdateModelTest extends TestCase
{
public function testGetExistsTables()
{
$pdo = PDOConnection::createConnection();
$dbs = new DbSchemaUpdateModel($pdo);
$table_list = $dbs->getExistsTables();
$this->assertIsArray($table_list);
}

public function testGetMigrateSqlList()
{
$pdo = PDOConnection::createConnection();
$dbs = new DbSchemaUpdateModel($pdo);
$sql_file_list = $dbs->getMigrateSqlList(0);
$this->assertIsArray($sql_file_list);

$sql_file_list = $dbs->getMigrateSqlList(99991010160000);
$this->assertEmpty($sql_file_list);
}

public function testGetTick()
{
$pdo = PDOConnection::createConnection();
$dbs = new DbSchemaUpdateModel($pdo);
$tick = $dbs->getNowTick();
$this->assertIsInt($tick);
}

public function testGetTickNumFromFileName()
{
$pdo = PDOConnection::createConnection();
$dbs = new DbSchemaUpdateModel($pdo);
$num = $dbs->getTickStringFromFileName("2021100101000000_test.sql");
$this->assertGreaterThan(1, $num);

try {
$dbs->getTickStringFromFileName("a2021100101000000_test.sql");
$this->fail();
} catch (\InvalidArgumentException $e) {
$this->assertTrue(true);
}

try {
$dbs->getTickStringFromFileName("a2021100101000000_test.sq");
$this->fail();
} catch (\InvalidArgumentException $e) {
$this->assertTrue(true);
}
}
}