2
0
Эх сурвалжийг харах

add createFromDsn factory with debug and logger support

phpdevcommunity 1 сар өмнө
parent
commit
6d1a0a7155

+ 1 - 1
composer.json

@@ -19,7 +19,7 @@
     ]
   },
   "require": {
-    "php": ">=7.4",
+    "php": ">=7.4|^8.0",
     "ext-pdo": "*",
     "ext-json": "*",
     "ext-ctype": "*",

+ 2 - 2
src/Command/Migration/MigrationDiffCommand.php

@@ -49,7 +49,7 @@ class MigrationDiffCommand implements CommandInterface
         $io = ConsoleOutput::create($output);
 
         $entitiesDir = $this->defaultEntitiesDir;
-        $output = $input->hasOption('output');
+        $printOutput = $input->getOptionValue('output');
         if ($input->hasOption('entities-dir')) {
             $entitiesDir = $input->getOptionValue('entities-dir');
         }
@@ -85,7 +85,7 @@ class MigrationDiffCommand implements CommandInterface
             return;
         }
 
-        if ($output === true) {
+        if ($printOutput === true) {
             $splFile = new \SplFileObject($file);
             $lines = [];
             while (!$splFile->eof()) {

+ 0 - 1
src/Command/Migration/MigrationMigrateCommand.php

@@ -55,7 +55,6 @@ class MigrationMigrateCommand implements CommandInterface
             $error = $exception->getMessage();
         }
 
-
         foreach ($successList as $version) {
             $io->success('Migration successfully executed: version ' . $version);
         }

+ 1 - 3
src/Command/ShowTablesCommand.php

@@ -8,7 +8,6 @@ use PhpDevCommunity\Console\InputInterface;
 use PhpDevCommunity\Console\Option\CommandOption;
 use PhpDevCommunity\Console\Output\ConsoleOutput;
 use PhpDevCommunity\Console\OutputInterface;
-use PhpDevCommunity\PaperORM\EntityManager;
 use PhpDevCommunity\PaperORM\EntityManagerInterface;
 use PhpDevCommunity\PaperORM\Metadata\ColumnMetadata;
 
@@ -70,7 +69,6 @@ class ShowTablesCommand implements CommandInterface
             $io->table(['Tables'], array_map(function (string $table) {
                 return [$table];
             }, $tables));
-            $io->writeln('');
         }else {
             foreach ($tables as $table) {
                 $io->title(sprintf('Table : %s', $table));
@@ -85,7 +83,7 @@ class ShowTablesCommand implements CommandInterface
                     $io->table(array_keys($columns[0]), $columns);
                 }
             }
-            $io->writeln('');
         }
+        $io->writeln('');
     }
 }

+ 62 - 35
src/Migration/PaperMigration.php

@@ -5,7 +5,6 @@ namespace PhpDevCommunity\PaperORM\Migration;
 use DateTime;
 use PDOException;
 use PhpDevCommunity\PaperORM\Entity\EntityInterface;
-use PhpDevCommunity\PaperORM\EntityManager;
 use PhpDevCommunity\PaperORM\EntityManagerInterface;
 use PhpDevCommunity\PaperORM\Generator\SchemaDiffGenerator;
 use PhpDevCommunity\PaperORM\Mapper\ColumnMapper;
@@ -15,6 +14,7 @@ use PhpDevCommunity\PaperORM\Mapping\Column\StringColumn;
 use PhpDevCommunity\PaperORM\PaperConnection;
 use PhpDevCommunity\PaperORM\Platform\PlatformInterface;
 use RuntimeException;
+use Throwable;
 use function date;
 use function file_get_contents;
 use function file_put_contents;
@@ -56,7 +56,7 @@ final class PaperMigration
     /**
      * @return array<string>
      */
-    public function getVersionAlreadyMigrated() : array
+    public function getVersionAlreadyMigrated(): array
     {
         $version = $this->getConnection()->fetchAll('SELECT version FROM ' . $this->tableName);
         return array_column($version, 'version');
@@ -65,11 +65,11 @@ final class PaperMigration
     public function generateMigration(array $sqlUp = [], array $sqlDown = []): string
     {
         $i = 1;
-        $file = date('YmdHis').$i . '.sql';
+        $file = date('YmdHis') . $i . '.sql';
         $filename = $this->directory->getDir() . DIRECTORY_SEPARATOR . $file;
         while (file_exists($filename)) {
             $i++;
-            $filename = rtrim($filename, ($i - 1).'.sql') . $i . '.sql';
+            $filename = rtrim($filename, ($i - 1) . '.sql') . $i . '.sql';
         }
 
         $migrationContent = <<<'SQL'
@@ -120,17 +120,7 @@ SQL;
 
     public function diffEntities(array $entities): ?string
     {
-        $tables = [];
-        foreach ($entities as $entity) {
-            if (is_subclass_of($entity, EntityInterface::class)) {
-                $tableName = EntityMapper::getTable($entity);
-                $tables[$tableName] = [
-                    'columns' => ColumnMapper::getColumns($entity),
-                    'indexes' => [] // TODO IndexMapper::getIndexes($entity)
-                ];
-            }
-        }
-        return $this->diff($tables);
+        return $this->diff(self::transformEntitiesToTables($entities));
     }
 
     public function diff(array $tables): ?string
@@ -149,16 +139,19 @@ SQL;
     public function up(string $version): void
     {
         $migration = $this->directory->getMigration($version);
-        $pdo = $this->getConnection()->getPdo();
+        $txDdl = $this->platform->supportsTransactionalDDL();
+        $conn = $this->getConnection();
+        $pdo = $conn->getPdo();
         try {
-            $pdo->beginTransaction();
+            if ($txDdl && !$pdo->inTransaction()) {
+                $pdo->beginTransaction();
+            }
             $executedQueries = [];
             foreach (explode(';' . PHP_EOL, self::contentUp($migration)) as $query) {
-                if (str_starts_with($query = trim($query), '--')) {
+                $executed = $this->executeQuery($query);
+                if ($executed === false) {
                     continue;
                 }
-                $query = rtrim($query, ';') . ';';
-                $this->getConnection()->executeStatement($query);
                 $executedQueries[] = $query;
             }
             if ($executedQueries === []) {
@@ -166,29 +159,36 @@ SQL;
             }
 
             $createdAt = (new DateTime())->format($this->platform->getSchema()->getDateTimeFormatString());
-            $rows = $this->getConnection()->executeStatement('INSERT INTO ' . $this->tableName . ' (version, created_at) VALUES (:version, :created_at)', ['version' => $version, 'created_at' => $createdAt]);
+            $rows = $conn->executeStatement('INSERT INTO ' . $this->tableName . ' (version, created_at) VALUES (:version, :created_at)', ['version' => $version, 'created_at' => $createdAt]);
             if ($rows == 0) {
                 throw new RuntimeException("Failed to execute insert for version : " . $version);
             }
-            $pdo->commit();
-        } catch (\Throwable $e) {
-            $pdo->rollBack();
+
+            if ($pdo->inTransaction()) {
+                $pdo->commit();
+            }
+        } catch (Throwable $e) {
+            if ($pdo->inTransaction()) {
+                $pdo->rollBack();
+            }
             throw new RuntimeException("Failed to migrate version $version : " . $e->getMessage());
         }
+
     }
 
     public function down(string $version): void
     {
         $migration = $this->directory->getMigration($version);
-        $pdo = $this->getConnection()->getPdo();
+        $conn = $this->getConnection();
+        $pdo = $conn->getPdo();
         $currentQuery = '';
         try {
             $pdo->beginTransaction();
             foreach (explode(';' . PHP_EOL, self::contentDown($migration)) as $query) {
                 $currentQuery = $query;
-                $this->getConnection()->executeStatement(rtrim($query, ';') . ';');
+                $this->executeQuery($query);
             }
-            $this->getConnection()->executeStatement('DELETE FROM ' . $this->tableName . ' WHERE version = :version', ['version' => $version]);
+            $conn->executeStatement('DELETE FROM ' . $this->tableName . ' WHERE version = :version', ['version' => $version]);
 
             $pdo->commit();
 
@@ -199,11 +199,21 @@ SQL;
 
     }
 
+    public function getSuccessList(): array
+    {
+        return $this->successList;
+    }
+
+    public function getEntityManager(): EntityManagerInterface
+    {
+        return $this->em;
+    }
+
     private function createVersion(): void
     {
         $this->platform->createTableIfNotExists($this->tableName, [
-            (new StringColumn( null, 50))->bindProperty('version'),
-            (new DateTimeColumn(null, 'created_at'))->bindProperty('created_at'),
+            new StringColumn('version', 50),
+            new DateTimeColumn('created_at', 'created_at'),
         ]);
     }
 
@@ -213,6 +223,17 @@ SQL;
 
     }
 
+    private function executeQuery(string $query): bool
+    {
+        $query = trim($query);
+        if (str_starts_with($query = trim($query), '--')) {
+            return false;
+        }
+        $query = rtrim($query, ';') . ';';
+        $this->getConnection()->executeStatement($query);
+        return true;
+    }
+
     private static function contentUp(string $migration): string
     {
         return trim(str_replace('-- UP MIGRATION --', '', self::content($migration)[0]));
@@ -231,13 +252,19 @@ SQL;
         return [trim($parts[0]), (isset($parts[1]) ? trim($parts[1]) : '')];
     }
 
-    public function getSuccessList(): array
+    private static function transformEntitiesToTables(array $entities): array
     {
-        return $this->successList;
-    }
+        $tables = [];
+        foreach ($entities as $entity) {
+            if (is_subclass_of($entity, EntityInterface::class)) {
+                $tableName = EntityMapper::getTable($entity);
+                $tables[$tableName] = [
+                    'columns' => ColumnMapper::getColumns($entity),
+                    'indexes' => [] // TODO IndexMapper::getIndexes($entity)
+                ];
+            }
+        }
 
-    public function getEntityManager(): EntityManagerInterface
-    {
-        return $this->em;
+        return $tables;
     }
 }

+ 5 - 0
src/Platform/MariaDBPlatform.php

@@ -291,6 +291,11 @@ class MariaDBPlatform extends AbstractPlatform
         return $this->schema;
     }
 
+    public function supportsTransactionalDDL(): bool
+    {
+        return false;
+    }
+
     public function executeStatement(string $sql): int
     {
         $result = 0;

+ 1 - 0
src/Platform/PlatformInterface.php

@@ -93,5 +93,6 @@ interface PlatformInterface
     public function getPrefixForeignKeyName(): string;
     public function diff(string $tableName, array $columns, array $indexes): DatabaseSchemaDiffMetadata;
     public function getSchema(): SchemaInterface;
+    public function supportsTransactionalDDL(): bool;
 }
 

+ 5 - 0
src/Platform/SqlitePlatform.php

@@ -299,4 +299,9 @@ class SqlitePlatform extends AbstractPlatform
     {
         return $this->schema;
     }
+
+    public function supportsTransactionalDDL(): bool
+    {
+       return true;
+    }
 }

+ 22 - 2
tests/DatabaseShowTablesCommandTest.php

@@ -39,7 +39,6 @@ class DatabaseShowTablesCommandTest extends TestCase
 
     private function executeTest(EntityManager $em)
     {
-
         $platform = $em->createDatabasePlatform();
         $platform->createDatabaseIfNotExists();
         $platform->dropDatabase();
@@ -64,9 +63,30 @@ class DatabaseShowTablesCommandTest extends TestCase
             new ShowTablesCommand($em)
         ]);
 
-        $code = $runner->run(new CommandParser(['', 'paper:show:tables', '--columns']), new Output(function ($message) use(&$countMessages) {
+        $out = [];
+        $code = $runner->run(new CommandParser(['', 'paper:show:tables', '--columns']), new Output(function ($message) use(&$out) {
+            $out[] = $message;
+        }));
+        $this->assertEquals(0, $code);
+        $this->assertEquals(132, count($out));
+
+        $out = [];
+        $code = $runner->run(new CommandParser(['', 'paper:show:tables', 'post']), new Output(function ($message) use(&$out) {
+            $out[] = $message;
         }));
+
         $this->assertEquals(0, $code);
+        $this->assertEquals(16, count($out));
 
+        $out = [];
+        $code = $runner->run(new CommandParser(['', 'paper:show:tables', 'post', '--columns']), new Output(function ($message) use(&$out) {
+            $out[] = $message;
+        }));
+
+        $this->assertEquals(0, $code);
+        $this->assertEquals(62, count($out));
+
+
+        $platform->dropDatabase();
     }
 }