Commit 01246fca authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Merge branch 'refact-database-service' into new-diff-strategy

parents 7da2bfc4 2b087e85
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -8,10 +8,13 @@ use Doctrine\DBAL\Platforms\PostgreSQL92Platform;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
use UnicaenDbImport\CodeGenerator\PostgreSQL\CodeGenerator as PostgreSQLCodeGenerator;
use UnicaenDbImport\CodeGenerator\PostgreSQL\CodeGeneratorFactory as PostgreSQLCodeGeneratorFactory;
use UnicaenDbImport\Config\Config;
use UnicaenDbImport\Config\ConfigFactory;
use UnicaenDbImport\Controller\ConsoleControllerFactory;
use UnicaenDbImport\Service\CodeGeneratorPluginManager;
use UnicaenDbImport\Service\CodeGeneratorPluginManagerFactory;
use UnicaenDbImport\Service\DatabaseService;
use UnicaenDbImport\Service\DatabaseServiceFactory;
use UnicaenDbImport\Service\ImportService;
use UnicaenDbImport\Service\ImportServiceFactory;
use UnicaenDbImport\Service\SynchroService;
@@ -68,8 +71,8 @@ return [
            Config::class => ConfigFactory::class,
            ImportService::class => ImportServiceFactory::class,
            SynchroService::class => SynchroServiceFactory::class,

            PostgreSQLCodeGenerator::class => PostgreSQLCodeGeneratorFactory::class,
            DatabaseService::class => DatabaseServiceFactory::class,
            CodeGeneratorPluginManager::class => CodeGeneratorPluginManagerFactory::class,
        ],
    ],
];
+33 −104
Original line number Diff line number Diff line
@@ -5,14 +5,13 @@ namespace UnicaenDbImport\CodeGenerator;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use UnicaenApp\Exception\RuntimeException;
use UnicaenApp\Util;
use UnicaenDbImport\CodeGenerator\Helper\DiffViewHelper;
use UnicaenDbImport\CodeGenerator\Helper\SynchroLogHelper;
use UnicaenDbImport\CodeGenerator\Helper\TableHelper;
use UnicaenDbImport\CodeGenerator\Helper\TableValidationHelper;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\Operation;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Domain\SourceInterface;
use UnicaenDbImport\Domain\Synchro;

/**
 * Classe mère des générateurs de code SQL, quelque soit la plateforme de base de données.
@@ -26,6 +25,11 @@ abstract class CodeGenerator implements CodeGeneratorInterface
     */
    protected $platform;

    /**
     * @var TableHelper
     */
    protected $tableHelper;

    /**
     * @var TableValidationHelper
     */
@@ -44,17 +48,15 @@ abstract class CodeGenerator implements CodeGeneratorInterface
    /**
     * AbstractCodeGenerator constructor.
     *
     * @param TableValidationHelper $tableValidationHelper
     * @param DiffViewHelper        $diffViewHelper
     * @param SynchroLogHelper      $synchroLogHelper
     * @param AbstractPlatform $platform
     */
    public function __construct(TableValidationHelper $tableValidationHelper,
                                DiffViewHelper $diffViewHelper,
                                SynchroLogHelper $synchroLogHelper)
    public function __construct(AbstractPlatform $platform)
    {
        $this->tableValidationHelper = $tableValidationHelper;
        $this->diffViewHelper = $diffViewHelper;
        $this->synchroLogHelper = $synchroLogHelper;
        $this->platform = $platform;

        //
        // NB: Les classes filles ont le responsabilité d'instancier les helpers concrets.
        //
    }

    /**
@@ -132,9 +134,8 @@ abstract class CodeGenerator implements CodeGeneratorInterface
        }

        $sourceTable = $source->getTable();
        $sql = "SELECT * FROM " . $sourceTable;

        return $sql;
        return $this->tableHelper->generateSQLForSelectFromTable($sourceTable);
    }

    /**
@@ -149,36 +150,17 @@ abstract class CodeGenerator implements CodeGeneratorInterface
        $sourceCodeColumn = $source->getSourceCodeColumn();
        $columns = $source->getColumns();

        $commaSeparatedColumnNames = implode(', ', array_merge([$sourceCodeColumn], $columns));

        $sqlTemplate = <<<'EOT'
create table {intermediateTable} as select {commaSeparatedColumnNames} from {destinationTable};
delete from {intermediateTable};
EOT;
        $sql = Util::tokenReplacedString($sqlTemplate, compact('intermediateTable', 'destinationTable', 'commaSeparatedColumnNames'));

        return $sql;
        return $this->tableHelper->generateSQLForIntermediateTableCreation($destinationTable, $sourceCodeColumn, $columns, $intermediateTable);
    }

    /**
     * @param string $tableName
     * @param array  $columnsValues
     * @return string
     */
    public function generateSQLForInsertIntoTable($tableName, array $columnsValues)
    {
        $platform = $this->platform;

        $commaSeparatedColumnNames = implode(', ', array_keys($columnsValues));
        $commaSeparatedColumnValues = implode(', ', array_map(function ($value) use ($platform) {
            if ($value === null) {
                return 'NULL';
            }

            return $platform->quoteStringLiteral($value);
        }, $columnsValues));

        $sqlTemplate = <<<'EOT'
insert into {tableName} ({commaSeparatedColumnNames}) values ({commaSeparatedColumnValues});
EOT;
        $sql = Util::tokenReplacedString($sqlTemplate, compact('tableName', 'commaSeparatedColumnNames', 'commaSeparatedColumnValues'));

        return $sql;
        return $this->tableHelper->generateSQLForInsertIntoTable($tableName, $columnsValues);
    }

    /**
@@ -194,10 +176,11 @@ EOT;

    /**
     * @return string
     * @codeCoverageIgnore
     */
    public function generateSQLForSynchroLogTableCreation()
    {
        throw CodeGeneratorException::methodToImplement(__METHOD__, get_called_class(), $this->platform);
        return $this->synchroLogHelper->generateSQLForSynchroLogTableCreation();
    }

    /**
@@ -227,24 +210,6 @@ EOT;
        return $this->diffViewHelper->generateSQLForCreation($diffSourceTableName, $destinationTable, $sourceCodeColumn, $columns);
    }

    /**
     * @param string $hash
     * @return string
     * @codeCoverageIgnore
     */
    public function generateSQLForFetchingSynchroLogTable($hash)
    {
        $tableName = Synchro::SYNCHRO_LOG_TABLE_NAME;

        $sql = '';
        $sql .= 'SELECT operation, source_code, table_name, field_name, from_value, to_value, created_on ';
        $sql .= "FROM $tableName ";
        $sql .= "WHERE import_hash = '$hash' ";
        $sql .= 'ORDER BY operation, table_name, field_name ;';

        return $sql;
    }

    /**
     * @param SourceInterface      $source
     * @param DestinationInterface $destination
@@ -263,63 +228,27 @@ EOT;
     * @param array                $rows
     * @param SourceInterface      $source
     * @param DestinationInterface $destination
     * @param string               $hash
     * @return string
     */
    public function generateSQLForDestinationUpdateFromDiffViewRequestResult(
        array $rows,
        SourceInterface $source,
        DestinationInterface $destination,
        $hash)
        DestinationInterface $destination)
    {
        $destinationTable = $destination->getTable();
        $sourceCodeColumn = $source->getSourceCodeColumn();
        $columns = $source->getColumns();

        // réorganisation par type d'opération
        $data = [];
        foreach ($rows as $row) {
            $operation = $row['operation'];
            if (!isset($data[$operation])) {
                $data[$operation] = [];
            }
            $data[$operation][] = $row;
        };

        $sqls = [];

        // une instruction SQL (update ou insert) par type d'opération suffira à mettre à jour la table destination
        $operations = array_keys($data);
        foreach ($operations as $operation) {
            switch ($operation) {
                case Operation::OPERATION_INSERT:
                    $sqls[] = $this->diffViewHelper->generateSQLForInsertOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                case Operation::OPERATION_UPDATE:
                    $sqls[] = $this->diffViewHelper->generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                case Operation::OPERATION_UNDELETE:
                    $sqls[] = $this->diffViewHelper->generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                case Operation::OPERATION_DELETE:
                    $sqls[] = $this->diffViewHelper->generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                default:
                    throw new RuntimeException("Opération inconnue rencontrée : " . $operation);
                    break;
        return $this->diffViewHelper->generateSQLForOperationInDestinationTableFromDiffViewRequestResult($rows, $destinationTable, $sourceCodeColumn, $columns);
    }
        }

        // génération des INSERT à faire dans la table
        $sqls[] = $this->synchroLogHelper->generateSQLForInsertsFromDiffResults(
            $rows,
            $destinationTable,
            $sourceCodeColumn,
            $columns,
            $hash);

        $sql = empty($sqls) ? '' : implode(PHP_EOL, $sqls);
    /**
     * @param ResultInterface $result
     * @return string
     */
    public function generateSQLForInsertResultIntoSynchroLog(ResultInterface $result)
    {
        return $this->synchroLogHelper->generateSQLForInsertResultIntoSynchroLogTable($result);

        return $sql;
    }
}
 No newline at end of file
+7 −9
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ namespace UnicaenDbImport\CodeGenerator;
use Doctrine\DBAL\DBALException;
use UnicaenApp\Exception\RuntimeException;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Domain\SourceInterface;

/**
@@ -88,12 +89,6 @@ interface CodeGeneratorInterface
     */
    public function generateSQLForIntermmediateTableDrop($tableName);

    /**
     * @param string $hash
     * @return string
     */
    public function generateSQLForFetchingSynchroLogTable($hash);

    /**
     * @param string $tableName
     * @return string
@@ -120,13 +115,16 @@ interface CodeGeneratorInterface
     * @param array                $rows
     * @param SourceInterface      $source
     * @param DestinationInterface $destination
     * @param string               $hash
     * @return string
     */
    public function generateSQLForDestinationUpdateFromDiffViewRequestResult(
        array $rows,
        SourceInterface $source,
        DestinationInterface $destination,
        $hash);
        DestinationInterface $destination);

    /**
     * @param ResultInterface $result
     * @return string
     */
    public function generateSQLForInsertResultIntoSynchroLog(ResultInterface $result);
}
 No newline at end of file
+13 −3
Original line number Diff line number Diff line
@@ -12,9 +12,19 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
abstract class Helper
{
    /**
     * @return AbstractPlatform
     * @var AbstractPlatform
     */
    abstract protected function getPlatform();
    protected $platform;

    /**
     * TableValidationHelper constructor.
     *
     * @param AbstractPlatform $platform
     */
    public function __construct(AbstractPlatform $platform)
    {
        $this->platform = $platform;
    }

    /**
     * @param string $argument
@@ -22,7 +32,7 @@ abstract class Helper
     */
    protected function getQuoteLiteralFunctionCallSQLSnippet($argument)
    {
        throw CodeGeneratorException::methodToImplement(__METHOD__, get_called_class(), $this->getPlatform());
        throw CodeGeneratorException::methodToImplement(__METHOD__, get_called_class(), $this->platform);
    }

    /**
+53 −6
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace UnicaenDbImport\CodeGenerator\Helper;

use Doctrine\DBAL\DBALException;
use UnicaenApp\Exception\RuntimeException;
use UnicaenDbImport\CodeGenerator\Helper;
use UnicaenDbImport\Domain\Operation;

@@ -94,7 +95,7 @@ EOT;
    {
        $name = $this->generateViewName($destinationTable);

        return $this->getPlatform()->getDropViewSQL($name);
        return $this->platform->getDropViewSQL($name);
    }

    /**
@@ -186,17 +187,63 @@ EOT;
        return $sql;
    }

    /**
     * @param array    $rows
     * @param string   $destinationTable
     * @param string   $sourceCodeColumn
     * @param string[] $columns
     * @return string
     */
    public function generateSQLForOperationInDestinationTableFromDiffViewRequestResult(array $rows, $destinationTable, $sourceCodeColumn, $columns)
    {
        // réorganisation par type d'opération
        $data = [];
        foreach ($rows as $row) {
            $operation = $row['operation'];
            if (!isset($data[$operation])) {
                $data[$operation] = [];
            }
            $data[$operation][] = $row;
        };

        $sqls = [];

        // une instruction SQL (update ou insert) par type d'opération suffira à mettre à jour la table destination
        $operations = array_keys($data);
        foreach ($operations as $operation) {
            switch ($operation) {
                case Operation::OPERATION_INSERT:
                    $sqls[] = $this->generateSQLForInsertOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                case Operation::OPERATION_UPDATE:
                    $sqls[] = $this->generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                case Operation::OPERATION_UNDELETE:
                    $sqls[] = $this->generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                case Operation::OPERATION_DELETE:
                    $sqls[] = $this->generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
                    break;
                default:
                    throw new RuntimeException("Opération inconnue rencontrée : " . $operation);
                    break;
            }
        }

        return empty($sqls) ? '' : implode(PHP_EOL, $sqls);
    }

    /**
     * @param string $destinationTable
     * @param string $sourceCodeColumn
     * @param array  $columns
     * @return string
     */
    public function generateSQLForInsertOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
    protected function generateSQLForInsertOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
    {
        $diffViewName = $this->generateViewName($destinationTable);

        $now = $this->getPlatform()->getNowExpression();
        $now = $this->platform->getNowExpression();

        $cols = array_merge([$sourceCodeColumn], $columns);
        $sourceCols = array_map(function ($col) {
@@ -220,7 +267,7 @@ EOT;
     * @param array $columns
     * @return string
     */
    abstract public function generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
    abstract protected function generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);

    /**
     * @param string $destinationTable
@@ -228,7 +275,7 @@ EOT;
     * @param array $columns
     * @return string
     */
    abstract public function generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
    abstract protected function generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);

    /**
     * @param string $destinationTable
@@ -236,5 +283,5 @@ EOT;
     * @param array $columns
     * @return string
     */
    abstract public function generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
    abstract protected function generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
}
 No newline at end of file
Loading