diff --git a/composer.json b/composer.json
index 8f9ad1fed0f34398c6b46cb296c68af5d6f32e69..6f1db68eae2a7c344ce34c6e885d8fe68f78f248 100644
--- a/composer.json
+++ b/composer.json
@@ -1,22 +1,22 @@
{
- "name" : "unicaen/bddadmin",
- "description" : "Module pour administrer des bases de données Postgresql et Oracle",
- "repositories": [
- {
- "type": "composer",
- "url" : "https://dev.unicaen.fr/packagist"
- }
- ],
- "require": {
- "php": ">=8.2"
- },
- "autoload" : {
- "psr-4" : {
- "Unicaen\\BddAdmin\\" : "src/",
- "Unicaen\\BddAdmin\\Tests\\" : "tests/"
- },
- "classmap": [
- "./Module.php"
- ]
+ "name": "unicaen/bddadmin",
+ "description": "Module pour administrer des bases de données Postgresql et Oracle",
+ "repositories": [
+ {
+ "type": "composer",
+ "url": "https://dev.unicaen.fr/packagist"
}
+ ],
+ "require": {
+ "php": ">=8.2"
+ },
+ "autoload": {
+ "psr-4": {
+ "Unicaen\\BddAdmin\\": "src/",
+ "Unicaen\\BddAdmin\\Tests\\": "tests/"
+ },
+ "classmap": [
+ "./Module.php"
+ ]
+ }
}
diff --git a/config/module.config.php b/config/module.config.php
index 7d4bc094a599921fa5d83ac2f0b6703c3f51acb8..bb7f7380ed94e5d3d05b031256053c394672fb6f 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -54,7 +54,17 @@ return [
'service_manager' => [
'factories' => [
- Bdd::class => BddFactory::class,
+ Bdd::class => BddFactory::class,
+ Command\UpdateBddCommand::class => Command\UpdateBddCommandFactory::class,
+ Command\UpdateDdlCommand::class => Command\UpdateDdlCommandFactory::class,
+ ],
+ ],
+
+
+ 'laminas-cli' => [
+ 'commands' => [
+ 'bddadmin:update-bdd' => Command\UpdateBddCommand::class,
+ 'bddadmin:update-ddl' => Command\UpdateDdlCommand::class,
],
],
];
\ No newline at end of file
diff --git a/src/Command/UpdateBddCommand.php b/src/Command/UpdateBddCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e75b266096f80a9e0c91d853aa1dfcdc5881e5b
--- /dev/null
+++ b/src/Command/UpdateBddCommand.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace Unicaen\BddAdmin\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Unicaen\BddAdmin\BddAwareTrait;
+use Unicaen\BddAdmin\Ddl\Ddl;
+
+/**
+ * Description of UpdateBddCommand
+ *
+ * @author Laurent Lécluse <laurent.lecluse at unicaen.fr>
+ */
+class UpdateBddCommand extends Command
+{
+ use BddAwareTrait;
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+ $bdd = $this->getBdd()->setLogger($io);
+
+ $io->title('Mise à jour de la base de données');
+ $io->info('Mise à jour des définitions de la base de données. Merci de patienter ...');
+
+ $ref = $bdd->getRefDdl();
+
+ // Construction de la config de DDL pour filtrer
+ $filters = [];
+ foreach ($ref as $ddlClass => $objects) {
+ foreach ($objects as $object => $objectDdl) {
+ $filters[$ddlClass]['includes'][] = $object;
+ }
+ }
+
+ $tablesDep = [
+ Ddl::INDEX,
+ Ddl::PRIMARY_CONSTRAINT,
+ Ddl::REF_CONSTRAINT,
+ Ddl::UNIQUE_CONSTRAINT,
+ ];
+
+ foreach ($tablesDep as $tableDep) {
+ $objects = $bdd->manager($tableDep)->get();
+ foreach ($objects as $obj) {
+ if (in_array($obj['table'], $filters['table']['includes'])) {
+ $filters[$tableDep]['includes'][] = $obj['name'];
+ }
+ }
+ }
+
+ // Initialisation et lancement de la pré-migration
+ //$mm = new MigrationManager($oa, $ref, $filters);
+ //$mm->migration('before');
+
+
+ // Mise à jour de la BDD (structures)
+ $bdd->alter($ref, $filters, true);
+
+
+ // Mise à jour des séquences
+ $bdd->majSequences($ref);
+
+
+ // Mise à jour des données
+ //$bdd->logBegin('Contrôle et mise à jour des données');
+ //$bdd->dataUpdater()->run('update');
+ //$bdd->logEnd('Données à jour');
+
+
+
+ // Post-migration
+ //$mm->migration('after');
+
+ return Command::SUCCESS;
+ }
+}
\ No newline at end of file
diff --git a/src/Command/UpdateBddCommandFactory.php b/src/Command/UpdateBddCommandFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..4b5ef7dc3dd9cb67cb2caa07fd7f986bbe8da14a
--- /dev/null
+++ b/src/Command/UpdateBddCommandFactory.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Unicaen\BddAdmin\Command;
+
+use Psr\Container\ContainerInterface;
+use Unicaen\BddAdmin\Bdd;
+
+
+/**
+ * Description of UpdateBddCommandFactory
+ *
+ * @author Laurent Lécluse <laurent.lecluse at unicaen.fr>
+ */
+class UpdateBddCommandFactory
+{
+
+ /**
+ * @param ContainerInterface $container
+ * @param string $requestedName
+ * @param array|null $options
+ *
+ * @return UpdateBddCommand
+ */
+ public function __invoke(ContainerInterface $container, $requestedName, $options = null): UpdateBddCommand
+ {
+ $command = new UpdateBddCommand;
+ $command->setBdd($container->get(Bdd::class));
+
+ return $command;
+ }
+}
\ No newline at end of file
diff --git a/src/Command/UpdateDdlCommand.php b/src/Command/UpdateDdlCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..9fdeecf80a7b4b84a8a23afc6912ca72d9329c09
--- /dev/null
+++ b/src/Command/UpdateDdlCommand.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Unicaen\BddAdmin\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Unicaen\BddAdmin\BddAwareTrait;
+
+/**
+ * Description of UpdateDdlCommand
+ *
+ * @author Laurent Lécluse <laurent.lecluse at unicaen.fr>
+ */
+class UpdateDdlCommand extends Command
+{
+ use BddAwareTrait;
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+ $bdd = $this->getBdd()->setLogger($io);
+
+ $filters = [
+ ];
+
+ $io->title('Génération de la DDL à partir de la base de données');
+
+ $ddl = $bdd->getDdl($filters);
+
+ $ddl->saveToDir();
+
+ return Command::SUCCESS;
+ }
+}
\ No newline at end of file
diff --git a/src/Command/UpdateDdlCommandFactory.php b/src/Command/UpdateDdlCommandFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..c6402da14da5ad5f4613fd8fa64efb8d85e779b5
--- /dev/null
+++ b/src/Command/UpdateDdlCommandFactory.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Unicaen\BddAdmin\Command;
+
+use Psr\Container\ContainerInterface;
+use Unicaen\BddAdmin\Bdd;
+
+
+/**
+ * Description of UpdateDdlCommandFactory
+ *
+ * @author Laurent Lécluse <laurent.lecluse at unicaen.fr>
+ */
+class UpdateDdlCommandFactory
+{
+
+
+ /**
+ * @param ContainerInterface $container
+ * @param string $requestedName
+ * @param array|null $options
+ *
+ * @return UpdateBddCommand
+ */
+ public function __invoke(ContainerInterface $container, $requestedName, $options = null): UpdateDdlCommand
+ {
+ $command = new UpdateDdlCommand;
+ $command->setBdd($container->get(Bdd::class));
+
+ return $command;
+ }
+}
\ No newline at end of file
diff --git a/src/Ddl/Ddl.php b/src/Ddl/Ddl.php
index c35c2b8b57f35fda565c9652d3510f09d1da3408..582da1e115fc0230fb679e086f66f9ddc14829f7 100644
--- a/src/Ddl/Ddl.php
+++ b/src/Ddl/Ddl.php
@@ -488,7 +488,13 @@ class Ddl implements Iterator, ArrayAccess
if ($name != '.' && $name != '..') {
$def = file_get_contents($dir . $type . '/' . $name);
$name = substr($name, 0, -4);
- $this->data[$type][$name] = ['name' => $name, 'definition' => $def];
+ if (str_contains($name, '.')) {
+ [$schema, $vmname] = Util::explodedFullObjectName($name);
+ $this->data[$type][$name] = ['schema' => $schema, 'name' => $vmname, 'definition' => $def];
+ }else{
+ $this->data[$type][$name] = ['name' => $name, 'definition' => $def];
+ }
+
}
}
}
diff --git a/src/Driver/Postgresql/FunctionManager.php b/src/Driver/Postgresql/FunctionManager.php
index 413b862b5f8ecbf6128f7d89111bda353df91533..06161dc4c82a17870d5b031ef4686664e3d411b7 100644
--- a/src/Driver/Postgresql/FunctionManager.php
+++ b/src/Driver/Postgresql/FunctionManager.php
@@ -106,6 +106,12 @@ class FunctionManager extends AbstractManager implements FunctionManagerInteface
public function alter(array $old, array $new): void
{
+ if (!isset($old['schema'])){
+ $old['schema'] = 'public';
+ }
+ if (!isset($new['schema'])){
+ $new['schema'] = 'public';
+ }
if ($old != $new) {
if ($this->sendEvent()->getReturn('no-exec')) return;
diff --git a/src/Driver/Postgresql/MaterializedViewManager.php b/src/Driver/Postgresql/MaterializedViewManager.php
index 3bbf40a3e29473d7bcb99607d5eee15c0f931053..cafef3bffc72bd7d9460538b496f0c124da29e51 100644
--- a/src/Driver/Postgresql/MaterializedViewManager.php
+++ b/src/Driver/Postgresql/MaterializedViewManager.php
@@ -78,7 +78,12 @@ class MaterializedViewManager extends AbstractManager implements MaterializedVie
public function alter(array $old, array $new): void
{
if ($this->sendEvent()->getReturn('no-exec')) return;
-
+ if (!isset($old['schema'])){
+ $old['schema'] = 'public';
+ }
+ if (!isset($new['schema'])){
+ $new['schema'] = 'public';
+ }
if ($old != $new) {
$this->drop($old);
$this->create($new);
diff --git a/src/Driver/Postgresql/ProcedureManager.php b/src/Driver/Postgresql/ProcedureManager.php
index 3405c3368cefbde60db8d72e3a618b0b14fea8fd..e37d230e7efc2d932b17cd48c4576a91cf4fc2ca 100644
--- a/src/Driver/Postgresql/ProcedureManager.php
+++ b/src/Driver/Postgresql/ProcedureManager.php
@@ -79,6 +79,12 @@ class ProcedureManager extends AbstractManager implements ProcedureManagerIntefa
public function alter(array $old, array $new): void
{
+ if (!isset($old['schema'])){
+ $old['schema'] = 'public';
+ }
+ if (!isset($new['schema'])){
+ $new['schema'] = 'public';
+ }
if ($old != $new) {
if ($this->sendEvent()->getReturn('no-exec')) return;
diff --git a/src/Driver/Postgresql/TableManager.php b/src/Driver/Postgresql/TableManager.php
index 8b30de009bf0d5b349310a39e14827c54fac99c6..9208502a8a4d5b978783a440b9ddfa0e90c39903 100644
--- a/src/Driver/Postgresql/TableManager.php
+++ b/src/Driver/Postgresql/TableManager.php
@@ -80,8 +80,7 @@ class TableManager extends AbstractManager implements TableManagerInterface
$q = "SELECT
ns.nspname \"schema\",
t.relname \"name\",
- 'N' \"temporary\",
- 'NO' logging,
+ t.relpersistence relpersistence,
c.column_name cname,
c.data_type \"type\",
c.character_maximum_length length,
@@ -113,8 +112,8 @@ class TableManager extends AbstractManager implements TableManagerInterface
$data[$name] = [
'schema' => $paq['schema'],
'name' => $paq['name'],
- 'temporary' => $paq['temporary'] == 'YES',
- 'logging' => $paq['logging'] == 'YES',
+ 'temporary' => $paq['relpersistence'] == 't',
+ 'logging' => $paq['relpersistence'] == 'p',
'commentaire' => $paq['commentaire'],
'sequence' => $paq['sequence'],
'columns' => [],
@@ -578,9 +577,8 @@ class TableManager extends AbstractManager implements TableManagerInterface
if ($this->sendEvent()->getReturn('no-exec')) return;
if ($old['logging'] !== $new['logging']) {
- throw new BddException("Il n'est pas possible actuellement de supprimer le logging d'une table ou de faire l'opération inverse");
- //$log = $new['logging'] ? 'LOGGING' : 'NOLOGGING';
- //$this->addQuery("ALTER TABLE $name $log", 'Modification du logging de la table ' . $name);
+ $sql = "ALTER TABLE $name SET ".($new['logging'] ? 'LOGGED' : 'UNLOGGED');
+ $this->addQuery($sql, 'Modification du logging de la table ' . $name);
}
$newCols = array_diff(array_keys($new['columns']), array_keys($old['columns']));
diff --git a/src/Driver/Postgresql/TriggerManager.php b/src/Driver/Postgresql/TriggerManager.php
index e42078311e4e9b85d7009258ac42b466197add1f..20a681c5c0dab4ac625b80ce132d7ca23be641d2 100644
--- a/src/Driver/Postgresql/TriggerManager.php
+++ b/src/Driver/Postgresql/TriggerManager.php
@@ -153,6 +153,12 @@ class TriggerManager extends AbstractManager implements TriggerManagerInterface
public function alter(array $old, array $new): void
{
+ if (!isset($old['schema'])){
+ $old['schema'] = 'public';
+ }
+ if (!isset($new['schema'])){
+ $new['schema'] = 'public';
+ }
if ($old != $new) {
if ($this->sendEvent()->getReturn('no-exec')) return;
diff --git a/src/Driver/Postgresql/ViewManager.php b/src/Driver/Postgresql/ViewManager.php
index a69159d3048a7ce27f8b55282f112543d71f3c0c..d8917d88e951fcf487b6e48a30339264b3d3c1a4 100644
--- a/src/Driver/Postgresql/ViewManager.php
+++ b/src/Driver/Postgresql/ViewManager.php
@@ -75,6 +75,12 @@ class ViewManager extends AbstractManager implements ViewManagerInterface
public function alter(array $old, array $new): void
{
+ if (!isset($old['schema'])){
+ $old['schema'] = 'public';
+ }
+ if (!isset($new['schema'])){
+ $new['schema'] = 'public';
+ }
if ($old != $new) {
if ($this->sendEvent()->getReturn('no-exec')) return;
diff --git a/src/Logger/DefaultLogger.php b/src/Logger/DefaultLogger.php
index cb82ff159b4665895cda3c4eab6bfdfb79c63fe3..4846a4917fd1fad32c667d896d56ea35d1c83244 100644
--- a/src/Logger/DefaultLogger.php
+++ b/src/Logger/DefaultLogger.php
@@ -54,7 +54,7 @@ class DefaultLogger implements LoggerInterface
- public function error($e)
+ public function error(Throwable|string $e)
{
if ($e instanceof \Throwable) {
$e = $e->getMessage();
diff --git a/src/Logger/LoggerAwareTrait.php b/src/Logger/LoggerAwareTrait.php
index 6c335419a067ded783e84a44289a6737de2d013f..399a64ed6758ee734dcd637760ef53f5c842cf53 100644
--- a/src/Logger/LoggerAwareTrait.php
+++ b/src/Logger/LoggerAwareTrait.php
@@ -2,6 +2,8 @@
namespace Unicaen\BddAdmin\Logger;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
trait LoggerAwareTrait
{
@@ -24,8 +26,11 @@ trait LoggerAwareTrait
*
* @return self
*/
- public function setLogger(?LoggerInterface $logger): self
+ public function setLogger(null|LoggerInterface|SymfonyStyle $logger): self
{
+ if ($logger instanceof SymfonyStyle){
+ $logger = new SymfonyStyleLogger($logger);
+ }
$this->logger = $logger;
return $this;
diff --git a/src/Logger/LoggerInterface.php b/src/Logger/LoggerInterface.php
index 51b7b437333782e57a7998557c74d4466cfaeee4..0d0aa4bf545a7fa0cc6210b3cc84243bcb57f349 100644
--- a/src/Logger/LoggerInterface.php
+++ b/src/Logger/LoggerInterface.php
@@ -4,7 +4,7 @@ namespace Unicaen\BddAdmin\Logger;
interface LoggerInterface
{
- public function error($e);
+ public function error(Throwable|string $e);
diff --git a/src/Logger/SymfonyStyleLogger.php b/src/Logger/SymfonyStyleLogger.php
new file mode 100644
index 0000000000000000000000000000000000000000..15307cf664ec0329b0f6f07a2c16674d0b87004e
--- /dev/null
+++ b/src/Logger/SymfonyStyleLogger.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Unicaen\BddAdmin\Logger;
+
+
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class SymfonyStyleLogger implements LoggerInterface
+{
+ protected ?string $lastMessage = null;
+
+ protected bool $lastRewrite = false;
+
+ protected SymfonyStyle $symfonyStyle;
+
+
+
+ public function __construct(SymfonyStyle $symfonyStyle)
+ {
+ $this->symfonyStyle = $symfonyStyle;
+ }
+
+
+
+ public function print($text, $color = null, $bgColor = null)
+ {
+ $this->symfonyStyle->write($text);
+ }
+
+
+
+ public function println($text, $color = null, $bgColor = null)
+ {
+ $this->symfonyStyle->writeln($text);
+ }
+
+
+
+ public function msg($message, bool $rewrite = false)
+ {
+ if ($rewrite) {
+ if ($this->lastMessage) {
+ $m = $message . str_pad('', strlen($this->lastMessage) - strlen($message) + 2) . "\r";
+ } else {
+ $m = $message . "\r";
+ }
+ $this->print($m);
+ } else {
+ $this->println($message);
+ }
+ $this->lastMessage = $message;
+ $this->lastRewrite = $rewrite;
+ }
+
+
+
+ public function error(Throwable|string $e)
+ {
+ if ($e instanceof \Throwable) {
+ $e = $e->getMessage();
+ }
+ if ($this->lastRewrite) $this->println('');
+ $this->symfonyStyle->error($e);
+ }
+
+
+
+ public function begin(string $title)
+ {
+ if ($this->lastMessage) {
+ $title .= str_pad('', strlen($this->lastMessage) - strlen($title) + 2);
+ }
+ $this->lastRewrite = false;
+ $this->lastMessage = null;
+ $this->symfonyStyle->title($title);
+ }
+
+
+
+ public function end(?string $msg = null): void
+ {
+ if ($this->lastMessage && $this->lastRewrite) {
+ $msg .= str_pad('', strlen($this->lastMessage) - strlen($msg ?? '') + 2);
+ }
+ if (trim($msg)) {
+ $this->symfonyStyle->comment($msg);
+ } else {
+ $this->println('');
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/Migration/MigrationManager.php b/src/Migration/MigrationManager.php
index 9edc1b05b743a2c004d7cb06a5fa308599cc22c1..f0b5569fe43417fcf8d5c90b129c690ce768a10e 100644
--- a/src/Migration/MigrationManager.php
+++ b/src/Migration/MigrationManager.php
@@ -11,7 +11,7 @@ class MigrationManager
{
use OptionsTrait;
- const string OPTION_DIR = 'dir';
+ const OPTION_DIR = 'dir';
protected Ddl $ref;
@@ -174,7 +174,7 @@ class MigrationManager
protected function getMigrationDir(): ?string
{
- $migrationDir = $this->getBdd()->getOption(Bdd::OPTION_MIGRATION_DIR);
+ $migrationDir = $this->getBdd()->getOption(self::OPTION_DIR);
return $migrationDir;
}