Loading Module.php +22 −1 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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'."], ]; } } config/module.config.php +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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' => [ Loading Loading @@ -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, Loading src/UnicaenOracle/Controller/Factory/IndexControllerFactory.php 0 → 100644 +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 src/UnicaenOracle/Controller/IndexController.php 0 → 100644 +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 src/UnicaenOracle/Service/DataService.php +12 −6 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading
Module.php +22 −1 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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'."], ]; } }
config/module.config.php +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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' => [ Loading Loading @@ -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, Loading
src/UnicaenOracle/Controller/Factory/IndexControllerFactory.php 0 → 100644 +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
src/UnicaenOracle/Controller/IndexController.php 0 → 100644 +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
src/UnicaenOracle/Service/DataService.php +12 −6 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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