Commit 0b50b7ec authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Nouvelle console action 'generate-db-scripts' pour générer les scripts SQL de...

Nouvelle console action 'generate-db-scripts' pour générer les scripts SQL de vidage, création, peuplement d'un schéma destination à partir d'un schéma source.
parent 740ab644
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -2,7 +2,10 @@

namespace UnicaenOracle;

class Module
use Zend\Console\Adapter\AdapterInterface;
use Zend\ModuleManager\Feature\ConsoleUsageProviderInterface;

class Module implements ConsoleUsageProviderInterface
{
    public function getConfig()
    {
@@ -19,4 +22,22 @@ class Module
            ),
        );
    }

    /**
     * @param AdapterInterface $console
     * @return array
     */
    public function getConsoleUsage(AdapterInterface $console)
    {
        return [
            // command
            'generate-db-scripts --src-schema=  --dst-schema= [--output-dir=] [--connection=]' =>
                "Générer les scripts SQL de vidage, création, peuplement d'un schéma destination à partir d'un schéma source.",
            // parameters
            ['--src-schema', "Requis. Nom du schema source, ex: 'SYGAL'."],
            ['--dst-schema', "Requis. Nom du schema destination, ex: 'SYGAL_TEST'."],
            ['--output-dir', "Facultatif. Chemin du répertoire où seront générés les scripts. Par défaut: '/tmp'."],
            ['--connection', "Facultatif. Nom de la connexion Doctrine à utiliser. Par défaut: 'doctrine.connection.orm_default'."],
        ];
    }
}
+28 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
namespace UnicaenOracle;

use Doctrine\DBAL\Driver\OCI8\Driver as OCI8;
use UnicaenOracle\Controller\Factory\IndexControllerFactory;
use UnicaenOracle\Controller\IndexController;
use UnicaenOracle\DBAL\Event\Listeners\OracleSessionInit;
use UnicaenOracle\ORM\Query\Functions\Chr;
use UnicaenOracle\ORM\Query\Functions\CompriseEntre;
@@ -10,6 +12,7 @@ use UnicaenOracle\ORM\Query\Functions\Convert;
use UnicaenOracle\ORM\Query\Functions\Replace;
use UnicaenOracle\Service\DataService;
use UnicaenOracle\Service\SchemaService;
use Zend\Mvc\Router\Console\Simple;

return [
    'doctrine' => [
@@ -38,6 +41,31 @@ return [
            ],
        ],
    ],
    'console' => [
        'router' => [
            'routes' => [
                'generate-db-scripts' => [
                    'type' => Simple::class,
                    'options' => [
                        'route'    => 'generate-db-scripts --src-schema=  --dst-schema= [--output-dir=] [--connection=]',
                        'defaults' => [
                            'controller' => IndexController::class,
                            'action'     => 'generateDbScriptsConsole',
                        ],
                    ],
                ],
            ],
        ],
        'view_manager' => [
            'display_not_found_reason' => true,
            'display_exceptions'       => true,
        ]
    ],
    'controllers' => [
        'factories' => [
            IndexController::class => IndexControllerFactory::class,
        ],
    ],
    'service_manager' => [
        'invokables' => [
            SchemaService::class => SchemaService::class,
+37 −0
Original line number Diff line number Diff line
<?php

namespace UnicaenOracle\Controller\Factory;

use UnicaenOracle\Controller\IndexController;
use UnicaenOracle\Service\DataService;
use UnicaenOracle\Service\SchemaService;
use Zend\Mvc\Controller\ControllerManager;

/**
 *
 *
 * @author Unicaen
 */
class IndexControllerFactory
{
    /**
     * @param ControllerManager $manager
     * @return IndexController
     */
    public function __invoke(ControllerManager $manager)
    {
        $sl = $manager->getServiceLocator();

        /** @var SchemaService $schemaService */
        $schemaService = $sl->get(SchemaService::class);

        /** @var DataService $dataService */
        $dataService = $sl->get(DataService::class);

        $controller = new IndexController();
        $controller->setSchemaService($schemaService);
        $controller->setDataService($dataService);

        return $controller;
    }
}
 No newline at end of file
+149 −0
Original line number Diff line number Diff line
<?php

namespace UnicaenOracle\Controller;

use Doctrine\DBAL\Connection;
use Doctrine\ORM\NoResultException;
use UnicaenApp\Exception\RuntimeException;
use UnicaenOracle\Service\Traits\DataServiceAwareTrait;
use UnicaenOracle\Service\Traits\SchemaServiceAwareTrait;
use Zend\Log\LoggerAwareTrait;
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    use SchemaServiceAwareTrait;
    use DataServiceAwareTrait;
    use LoggerAwareTrait;

    /**
     * Action en mode CLI.
     */
    public function generateDbScriptsConsoleAction()
    {
        $srcSchema = $this->params('src-schema'); // ex: 'SYGAL'
        $dstSchema = $this->params('dst-schema'); // ex: 'SYGAL_TEST'
        $destDir = $this->params('output-dir', '/tmp'); // ex: '/tmp'
        $connName = $this->params('connection', 'doctrine.connection.orm_default');

        /** @var Connection $srcSchemaConn */
        $srcSchemaConn = $this->getServiceLocator()->get($connName);

        $this->log("=================================");
        $this->log("Database schema scripts generator");
        $this->log("=================================");

        /**
         * Schema clearing.
         */
        $this->log("# Generating database clearing scripts...");
        $outputFilePath = $destDir . "/oracle-clear-schema-$dstSchema.sql";
        try {
            $this->schemaService->createSchemaClearingScriptFile($srcSchemaConn, $dstSchema, $outputFilePath);
        } catch (NoResultException $e) {
            throw new RuntimeException(
                "Impossible de générer le script de vidage du schéma '$dstSchema'. 
                Peut-être est-il déjà vide ou alors le schéma n'est pas accessible avec la connexion utilisée.");
        }
        $this->log($outputFilePath);

        /**
         * Schema creation.
         */
        $this->log("# Generating schema creation script...");
        $outputFilePath = $destDir . "/oracle-generate-schema-$dstSchema-from-$srcSchema.sql";
        $this->schemaService->createSchemaCreationScriptFile($srcSchemaConn, $srcSchema, $dstSchema, $outputFilePath);
        $this->log($outputFilePath);

        /**
         * Data inserts.
         */
        $this->log("# Generating data inserts scripts...");
        $tableNames = [
            'ACTEUR',
            'ATTESTATION',
            'CATEGORIE_PRIVILEGE',
            'DIFFUSION',
            'DOCTORANT',
            'DOCTORANT_COMPL',
            'DOMAINE_SCIENTIFIQUE',
            'ECOLE_DOCT',
            'ETABLISSEMENT',
            'ETABLISSEMENT_RATTACH',
            'FAQ',
            'FICHIER',
            'FINANCEMENT',
            'IMPORT_NOTIF',
            'IMPORT_OBS_NOTIF',
            'IMPORT_OBS_RESULT_NOTIF',
            'IMPORT_OBSERV',
            'IMPORT_OBSERV_RESULT',
            'INDICATEUR',
            'INDIVIDU',
            'INDIVIDU_ROLE',
            'MAIL_CONFIRMATION',
            'METADONNEE_THESE',
            'NATURE_FICHIER',
            'NOTIF',
            'NOTIF_RESULT',
            'ORIGINE_FINANCEMENT',
            'PRIVILEGE',
            'RDV_BU',
            'ROLE',
            'ROLE_MODELE',
            'ROLE_PRIVILEGE',
            'ROLE_PRIVILEGE_MODELE',
            'SOURCE',
            'STRUCTURE',
            'STRUCTURE_SUBSTIT',
            'SYNC_LOG',
            'SYNCHRO_LOG',
            'THESE',
            'TITRE_ACCES',
            'TMP_ACTEUR',
            'TMP_DOCTORANT',
            'TMP_ECOLE_DOCT',
            'TMP_ETABLISSEMENT',
            'TMP_FINANCEMENT',
            'TMP_INDIVIDU',
            'TMP_ORIGINE_FINANCEMENT',
            'TMP_ROLE',
            'TMP_STRUCTURE',
            'TMP_THESE',
            'TMP_TITRE_ACCES',
            'TMP_UNITE_RECH',
            'TMP_VARIABLE',
            'TYPE_STRUCTURE',
            'TYPE_VALIDATION',
            'UNITE_DOMAINE_LINKER',
            'UNITE_RECH',
            'UTILISATEUR',
            'VALIDATION',
            'VALIDITE_FICHIER',
            'VARIABLE',
            'VERSION_FICHIER',
            'WF_ETAPE',
        ];
        $outputFilePathTemplate = $destDir . "/oracle-data-insert-from-$srcSchema.%s-into-$dstSchema.sql";
        $outputFilePaths = $this->dataService->createDataInsertsScriptFile($srcSchemaConn, $dstSchema, $tableNames, $outputFilePathTemplate);
        foreach ($outputFilePaths as $outputFilePath) {
            $this->log($outputFilePath);
        }

        $this->log("Done.");

        exit(0);
    }

    /**
     * @param string $message
     */
    private function log($message)
    {
        if ($this->logger !== null) {
            $this->logger->info($message);
        } else {
            echo $message . PHP_EOL;
        }
    }
}
 No newline at end of file
+12 −6
Original line number Diff line number Diff line
@@ -99,20 +99,23 @@ EOS;
            $colName = $row['COLUMN_NAME'];
            $dataType = $row['DATA_TYPE'];

            switch ($dataType) {
                case 'NUMBER':
            switch (true) {

                case $dataType === 'NUMBER':
                    $formatter = function ($value) {
                        return $value;
                    };
                    break;
                case 'VARCHAR2':

                case $dataType === 'VARCHAR2':
                    $formatter = function ($value) {
                        $value = str_replace("'", "''", $value);

                        return "'$value'";
                    };
                    break;
                case 'CLOB':

                case $dataType === 'CLOB':
                    $formatter = function ($value) {
                        $value = str_replace("'", "''", $value);
                        // découpage en morceaux de 4000 caractères pour éviter l'erreur ORA-01704: string literal too long.
@@ -125,13 +128,16 @@ EOS;
                        return implode('||', $toClobs);
                    };
                    break;
                case 'DATE':

                case $dataType === 'DATE':
                case substr($dataType, 0, 9) === 'TIMESTAMP':
                    $formatter = function ($value) {
                        return "TO_DATE('$value', 'YYYY-MM-DD HH24:MI:SS')";
                    };
                    break;

                default:
                    throw new RuntimeException("Type non prévu : $dataType");
                    throw new RuntimeException("Type imprévu rencontré dans la table '$tableName' : $dataType.");
            }
            $cfg = [
                'DATA_TYPE' => $dataType,
Loading