Skip to content
Snippets Groups Projects
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
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
namespace UnicaenOracle; namespace UnicaenOracle;
class Module use Zend\Console\Adapter\AdapterInterface;
use Zend\ModuleManager\Feature\ConsoleUsageProviderInterface;
class Module implements ConsoleUsageProviderInterface
{ {
public function getConfig() public function getConfig()
{ {
...@@ -19,4 +22,22 @@ class Module ...@@ -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'."],
];
}
} }
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
namespace UnicaenOracle; namespace UnicaenOracle;
use Doctrine\DBAL\Driver\OCI8\Driver as OCI8; 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\DBAL\Event\Listeners\OracleSessionInit;
use UnicaenOracle\ORM\Query\Functions\Chr; use UnicaenOracle\ORM\Query\Functions\Chr;
use UnicaenOracle\ORM\Query\Functions\CompriseEntre; use UnicaenOracle\ORM\Query\Functions\CompriseEntre;
...@@ -10,6 +12,7 @@ use UnicaenOracle\ORM\Query\Functions\Convert; ...@@ -10,6 +12,7 @@ use UnicaenOracle\ORM\Query\Functions\Convert;
use UnicaenOracle\ORM\Query\Functions\Replace; use UnicaenOracle\ORM\Query\Functions\Replace;
use UnicaenOracle\Service\DataService; use UnicaenOracle\Service\DataService;
use UnicaenOracle\Service\SchemaService; use UnicaenOracle\Service\SchemaService;
use Zend\Mvc\Router\Console\Simple;
return [ return [
'doctrine' => [ 'doctrine' => [
...@@ -38,6 +41,31 @@ return [ ...@@ -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' => [ 'service_manager' => [
'invokables' => [ 'invokables' => [
SchemaService::class => SchemaService::class, SchemaService::class => SchemaService::class,
......
<?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
<?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
...@@ -99,20 +99,23 @@ EOS; ...@@ -99,20 +99,23 @@ EOS;
$colName = $row['COLUMN_NAME']; $colName = $row['COLUMN_NAME'];
$dataType = $row['DATA_TYPE']; $dataType = $row['DATA_TYPE'];
switch ($dataType) { switch (true) {
case 'NUMBER':
case $dataType === 'NUMBER':
$formatter = function ($value) { $formatter = function ($value) {
return $value; return $value;
}; };
break; break;
case 'VARCHAR2':
case $dataType === 'VARCHAR2':
$formatter = function ($value) { $formatter = function ($value) {
$value = str_replace("'", "''", $value); $value = str_replace("'", "''", $value);
return "'$value'"; return "'$value'";
}; };
break; break;
case 'CLOB':
case $dataType === 'CLOB':
$formatter = function ($value) { $formatter = function ($value) {
$value = str_replace("'", "''", $value); $value = str_replace("'", "''", $value);
// découpage en morceaux de 4000 caractères pour éviter l'erreur ORA-01704: string literal too long. // découpage en morceaux de 4000 caractères pour éviter l'erreur ORA-01704: string literal too long.
...@@ -125,13 +128,16 @@ EOS; ...@@ -125,13 +128,16 @@ EOS;
return implode('||', $toClobs); return implode('||', $toClobs);
}; };
break; break;
case 'DATE':
case $dataType === 'DATE':
case substr($dataType, 0, 9) === 'TIMESTAMP':
$formatter = function ($value) { $formatter = function ($value) {
return "TO_DATE('$value', 'YYYY-MM-DD HH24:MI:SS')"; return "TO_DATE('$value', 'YYYY-MM-DD HH24:MI:SS')";
}; };
break; break;
default: default:
throw new RuntimeException("Type non prévu : $dataType"); throw new RuntimeException("Type imprévu rencontré dans la table '$tableName' : $dataType.");
} }
$cfg = [ $cfg = [
'DATA_TYPE' => $dataType, 'DATA_TYPE' => $dataType,
......
<?php
namespace UnicaenOracle\Service\Traits;
use UnicaenOracle\Service\DataService;
trait DataServiceAwareTrait
{
/**
* @var DataService
*/
protected $dataService;
/**
* @param DataService $dataService
*/
public function setDataService(DataService $dataService)
{
$this->dataService = $dataService;
}
}
\ No newline at end of file
<?php
namespace UnicaenOracle\Service\Traits;
use UnicaenOracle\Service\SchemaService;
trait SchemaServiceAwareTrait
{
/**
* @var SchemaService
*/
protected $schemaService;
/**
* @param SchemaService $schemaService
*/
public function setSchemaService(SchemaService $schemaService)
{
$this->schemaService = $schemaService;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment