Skip to content
Snippets Groups Projects
Select Git revision
  • fe9305e2fc9c64edf9708b51d870d1c159cf41d8
  • master default protected
  • release_7.2.1
  • release_7.2.0
  • unicaen_authentification
  • release_6.1.2
  • release_6.0.4
  • release_6.1.0
  • release_6.0.3
  • 6.1.0
  • smile
  • 5.x
  • release_5.2.2
  • utilisateur
  • release_5.2.1
  • laminas-bs5-UnicaenPrivilege
  • feature_import_one_row
  • laminas_migration
  • PHP_7-4
  • release_4.0.2
  • release_4.0.0
  • 7.2.1
  • 7.2.0
  • 7.1.0
  • 6.2.0
  • 7.0.0
  • 6.1.4
  • 6.1.3
  • 6.1.2
  • 6.1.1
  • 6.1.0
  • 6.0.3
  • 6.0.2
  • 5.2.3
  • 6.0.1
  • 6.0.0
  • 5.2.2
  • emc2_1.0.0
  • 5.2.1
  • 5.2.0
  • 5.1.2
41 results

db-import

  • Clone with SSH
  • Clone with HTTPS
  • Bertrand GAUTHIER's avatar
    Bertrand Gauthier authored
    [FIX] Import : seules les données issues de la source concernée doivent être préalablement purgées, pas toute la table.
    fe9305e2
    History

    UnicaenDbImport

    NB: Refonte en cours, plus d'information sur l'ancien moteur (peut être encore actuel) d'UnicaenDbImport en cliquant ici.

    Installation

    • Ensuite, ajoutez le module à vos dépendances :
    composer require unicaen/db-import

    Introduction

    Ce module réalise l'import et/ou la synchronisation de données issues d'une source vers une table d'une base de données destination.

    La source peut être :

    • soit une table ou un "select" dans une base de données,
    • soit une API (web service).

    La destination est forcément une table dans une base de données.

    L'import et la synchronisation sont 2 mécanismes distincts.

    Import

    Principe de l'import :

    • La table destination est vidée entièrement.
    • Les données obtenues de la source sont insérées dans la table destination.

    Synchronisation

    Principe de la synchronisation :

    • Si la source contient un enregistrement qui n'existe pas dans la destination, il est ajouté dans cette dernière.
    • Si la source contient un enregistrement qui existe aussi dans la destination avec les mêmes valeurs de colonnes, rien n'est fait.
    • Si la source contient un enregistrement qui existe aussi dans la destination mais avec des valeurs de colonnes différentes, les colonnes de la destination sont mises à jour en conséquence.
    • Si la source ne contient pas un enregistrement qui existe dans la destination, l'enregistrement destination est historisé (i.e. marqué "supprimé").
    • Si la source contient un enregistrement qui existe aussi dans la destination mais marqué "supprimé", ce dernier est dé-historisé.

    Les données source et les données destination doivent avoir un identifiant unique en commun, permettant de les rapprocher : on l'appellera le "code source" (cf. paramètre de config source_code_column).

    Cet identifiant commun DOIT être de type chaîne de caractères.

    Afin de faciliter l'adaptation au plus grand nombre de plateforme de base de données, UnicaenDbImport s'appuie en partie sur l'ORM Doctrine 2.

    Différence avec unicaen/import

    Comme son nom ne l'indique pas, "unicaen/import" fonctionne uniquement entre 2 bases de données Oracle.

    Le présent module "unicaen/db-import" fonctionne en majeure partie en PHP, tout en déléguant au maximum au SGBD ce que ce dernier sait bien faire (select FULL OUTER JOIN pour le différentiel entre données source et données destination, par exemple).

    Par conséquent, il est possible de l'enrichir pour implémenter imports et synchros vers différentes plateformes de base de données destination. Les plateformes de base de données destination suivantes sont implementées :

    • PostgreSQL
    • Oracle

    En revanche toutes les plateformes de base de données source sont supportées car on se contente d'y faire un select pour obtenir les données.

    Installation

    Première installation

    • Installez le module :
    composer require unicaen/db-import
    • Ajoutez dans le composer.json de votre appli, la "post install command" suivante :
        "scripts": {
            "post-install-cmd": [
                "mkdir -p public/unicaen ; cp -r vendor/unicaen/db-import/public/unicaen public/",
    • Lancer les "post install commands" de votre appli pour obtenir les ressources CSS et JS du module :
    composer run-script post-install-cmd
    • Reportez-vous dans le répertoire data au script SQL correspondant à votre plateforme de base de données destination pour créer les objets nécessaires. Notamment la table SOURCE permettant de déclarer les différentes sources de données disponibles (ex : Apogée, Harpege, Octopus).

    Mise à jour

    Lorsqu'une nouvelle version du module est installée dans votre appli, n'oubliez pas de relancer les "post install commands" de votre appli pour obtenir les versions à jour des ressources CSS et JS :

    composer run-script post-install-cmd

    Configuration

    • Récupérez les fichiers config exemples :
    cp -n vendor/unicaen/db-import/config/unicaen-db-import.global.php.dist config/autoload/unicaen-db-import.global.php
    cp -n vendor/unicaen/db-import/config/unicaen-db-import.local.php.dist config/autoload/unicaen-db-import.local.php
    • Adaptez leur contenu à vos besoins en lisant bien les commentaires inclus.

    • Ajoutez ce qui suit à la config du module "unicaen/bjy-authorize" si vous l'utilisez :

    return [
        'bjyauthorize'    => [
            'guards' => [
                \UnicaenAuth\Guard\PrivilegeController::class => [
                    [
                        'controller' => 'UnicaenDbImport\Controller\Console',
                        'action'     => [
                            'runImport',
                            'runSynchro',
                        ],
                        'roles' => [],
                    ],
                ],
            ],
        ],
        //...
    ];

    Utilisation

    Le module propose deux opérations distinctes :

    1. Import : réalise un import "brut" des données, autrement dit une copie de données de la source vers la destination ;
    2. Synchro : réalise une synchronisation unidirectionnelle de la destination à partir de la source.

    Le module fournit une ligne de commande pour lancer :

    • un import par son nom :
    php public/index.php run import --name "NOM_ETABLI_DANS_LA_CONFIG"
    • tous les imports :
    php public/index.php run import
    • une synchro par son nom :
    php public/index.php run synchro --name "NOM_ETABLI_DANS_LA_CONFIG"
    • toutes les synchros :
    public/index.php run synchro

    NB : Chacune de ces commandes réalise l'import ou la synchronisation une seule fois. Pour importer/synchroniser en permanence, il faut programmer le lancement périodique de la commande à l'aide de CRON par exemple. Ex : */15 6-19 * * 1-5 root /usr/bin/php /path/to/app/public/index.php run import --all 1> /tmp/zebu-cron.log 2>&1

    Contraintes

    Identifiant commun

    Les données source doivent posséder un identifiant unique/discriminant (cf. paramètre de config source_code_column) de type chaîne de caractères.

    Dans le cas d'une synchro, la table destination doit posséder aussi cet identifiant unique/discriminant permettant de rapprocher les données source et destination.

    Table SOURCE

    La base de données destination doit posséder une table particulière nommée SOURCE dont le script de création est fourni dans le répertoire data.

    Cette table permet de nommer et de référencer les différentes sources de données disponibles (ex : Apogée, Harpege, Octopus) et d'indiquer lesquelles sont importables/synchronisables. Elle contient a minima une source : l'application elle-même, source non importable/synchronisable par principe.

    Dans le cas d'un import/synchro depuis une source de type API, l'attribut de config 'code' de la source doit correspondre au CODE d'une source dans la table SOURCE, sinon une erreur sera signalée.

    Table destination

    Colonnes pour l'historique

    La table destination doit obligatoirement posséder les colonnes permettant de gérer l'historique (cycle de vie) des données :

    • created_on : date et heure de création de la donnée
    • updated_on : date et heure de modification
    • deleted_on : date et heure de suppression (historisation)
    • created_by : id de l'auteur de la création
    • updated_by : id de l'auteur de la modification
    • deleted_by : id de l'auteur de la suppression (historisation)

    Exemple en PostgreSQL :

    ALTER TABLE TABLE_DESTINATION ADD COLUMN created_on TIMESTAMP(0) WITH TIME ZONE DEFAULT LOCALTIMESTAMP(0) NOT NULL;
    ALTER TABLE TABLE_DESTINATION ADD COLUMN updated_on TIMESTAMP(0) WITH TIME ZONE;
    ALTER TABLE TABLE_DESTINATION ADD COLUMN deleted_on TIMESTAMP(0) WITH TIME ZONE;
    ALTER TABLE TABLE_DESTINATION ADD COLUMN created_by INTEGER NOT NULL;
    ALTER TABLE TABLE_DESTINATION ADD COLUMN updated_by INTEGER;
    ALTER TABLE TABLE_DESTINATION ADD COLUMN deleted_by INTEGER;

    Si vous utilisez un autre nommage pour ces colonnes dans la table destination, il est possible de renseigner dans la config les alias pour chaque colonne. Le type des colonnes, lui, en revanche devra être respecté.

    Si vous ne souhaitez pas consigner l'auteur des créations, vous devrez retirer le NOT NULL sur la colonne created_by.

    Remarque importante : la disparition d'un enregistrement dans la source ne provoque pas sa supression physique dans la table destination ; ce dernier est simplement "marqué comme supprimé" (historisé) à l'aide des colonnes d'historique deleted_on (date et heure de suppression) et deleted_by (identifiant de l'auteur de la suppression).

    Colonnes source_id et source_code

    La table destination doit obligatoirement posséder les colonnes suivantes :

    • source_id : clé étrangère identifiant la source de la donnée, correspondant à un 'id' de la [table SOURCE](#Table SOURCE).
    • source_code : fameux identifiant commun permettant de rapprocher la donnée source de la donnée destination.

    Exemple en PostgreSQL :

    ALTER TABLE TABLE_DESTINATION ADD source_id integer NOT NULL ;
    ALTER TABLE TABLE_DESTINATION ADD source_code varchar(100) ;

    Fonctionnement

    Import

    Typiquement, il s'agit d'importer des données issues d'une base de données source (différente de celle de celle de destination) ou d'une API (web service).

    Schéma du déroulement d'un import :

    fonctionnement_import.png

    1. Suppression totale des données existantes dans la table destination.
    2. Interrogation de la source pour obtenir les données sources.
    3. Génération des requêtes SQL d'INSERT.
    4. Exécution des requêtes d'INSERT dans la table destination.

    Synchronisation "locale"

    Ce que l'on appelle synchronisation locale consiste à synchroniser le contenu d'une table destination à partir de celui d'une table (ou d'un "select") source se trouvant dans la même base de données.

    Schéma du déroulement d'une synchro :

    fonctionnement_synchro_locale.png

    1. Création d'une vue différentielle (différences entre les données de la table/vue source et celles de la table destination).
    2. Préparation des opérations à réaliser sur la table destination (INSERT ou UPDATE) à partir de ce que fournit la vue différentielle.
    3. Réalisations des opérations dans la table destination.

    Synchronisation à partir d'une source "externe"

    Dans une synchronisation à partir d'une source dite "externe", la source peut être de 2 natures :

    • soit une table ou un select provenant d'une autre base de données que celle de destination,
    • soit une API (web service).

    Quelle que soit la nature de la source, cette synchronisation se subdivisera en 2 sous-tâches successives : un import puis une synchronisation locale.

    Schématisation du déroulement d'une synchro à partir d'une source "externe" :

    fonctionnement_synchro_distant.png

    1. Import des données sources dans une table intermédiaire de la base de données destination.
    2. Synchronisation locale entre la table intermédiaire (devenue source) et la table destination.
    3. Suppression de la table temporaire.

    Exemples

    Pour les exemples suivants, on suppose posséder :

    • Une base de donnée A (celle de notre application) contenant les tables :
      • UTILISATEUR(int ID, str CODE, str NOM, str PRENOM, date NAISSANCE)
      • AUTRE_UTILISATEUR(str CODE, str NOM, str PRENOM, date NAISSANCE)
      • COMPOSANTE(int ID, str CODE, str NOM)
      • FORMATION(int ID, str CODE, str NOM, str COMPOSANTE_ID)
      • PAIN_AU_CHOCOLAT(int ID, str NOM, str BOULANGERIE)
    • Une base de donnée B différente de A (par exemple Apogée) contenant les tables :
      • UTILISATEUR(int ID, str CODE, str NOM, str PRENOM, date NAISSANCE)
      • COMPOSANTE(int ID, str CODE, str NOM, int DIRECTEUR_ID, str ADRESSE)
      • FORMATION(int ID, str CODE, str NOM, str COMPOSANTE_CODE)
      • CHOCOLATINE(int ID, str NOM, str BOULANGERIE, int POURCENT_GRAS, int NOTE)

    En outre, on suppose avoir déclaré les connexions orm_A et orm_B respectivement pour les bases A et B (dans le fichier de config config/autoload/unicaen-db-import.local.php par exemple, inspiré du ficher de config exemple unicaen-db-import.local.php.dist).

    Pour les exemples qui suivent, voici à quoi ressemble le fichier de config config/unicaen-db-import.local.php :

    unicaen-db-import.local.php

    return [
        'import' => [
            'connections' => [
                'orm_A' => 'doctrine.connection.orm_A',
                'orm_B' => 'doctrine.connection.orm_B',
                'geo' => [
                    'url'      => 'https://geo.api.gouv.fr/',
                    'proxy'    => false,
                    'verify'   => true,
                    'user'     => null,
                    'password' => null,
                ],
            ],
        ],
        'doctrine' => [
            'connection' => [
                'orm_A' => [
                    'driverClass' => 'Doctrine\\DBAL\\Driver\\PDOPgSql\\Driver',
                    'params' => [
                        'host'     => 'host.domain.fr',
                        'port'     => '5432',
                        'charset'  => 'utf8',
                        'user'     => '???',
                        'dbname'   => '???',
                        'password' => '???',
                    ],
                ],
                'orm_B' => [
                    'driverClass' => 'Doctrine\\DBAL\\Driver\\OCI8\\Driver',
                    'params'      => [
                        'host'     => 'host.domain.fr',
                        'port'     => '1527',
                        'user'     => '???',
                        'password' => '???',
                        'dbname'   => '???',
                        'charset'  => 'AL32UTF8',
                    ],
                    'eventmanager' => 'orm_B',
                ],
            ],
        ],
    ];

    Exemple 1 : Import de données externes provenant d'une autre base

    Dans de nombreux cas, on souhaite importer une table (ou une vue ou un "select") de données provenant d'une autre base que celle de destination. Ce peut être utile par exemple pour disposer de données externes sans être impacté par une indisponibilité de la base de données source (en cas de maintenance par exemple).

    unicaen-db-import.global.php

    return [
        'import' => [
            'imports' => [
                [
                    'name' => "IMPORT_SIMPLE",
                    'source' => [
                        'code'               => 'UTILISATEUR_OCTOPUS',
                        'table'              => 'UTILISATEUR', 
                        'connection'         => 'orm_B',
                        'source_code_column' => 'CODE',
                    ],
                    'destination' => [
                        'code'               => 'TABLE UTILISATEUR LOCALE',
                        'table'              => 'UTILISATEUR',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'CODE',
                    ],
                ],
            ],
        ],
    ];

    Ligne de commande :

    php public/index.php run import --name "IMPORT_SIMPLE"

    Exemple 2 : Import de données externes issues d'une API

    Dans certains cas, on souhaite importer les données provenant d'une API (web service).

    unicaen-db-import.global.php

    return [
        'import' => [
            'imports' => [
                [
                    'name' => "IMPORT_REGIONS_API",
                    'source' => [
                        'code'               => 'geo_api', // DOIT correspondre à un `CODE` de la table `SOURCE`
                        'select'             => '/regions?fields=nom,code',
                        'connection'         => 'geo',
                        'source_code_column' => 'code',
                    ],
                    'destination' => [
                        'code'               => 'Table REGION',
                        'table'              => 'REGION',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'CODE',
                    ],
                ],
            ],
        ],
    ];

    Dans ce type de source, le select est la partie "requête" qui sera concaténée à l'url de l'API spécifiée dans la config de la connexion.

    Ligne de commande :

    php public/index.php run import --name "IMPORT_REGIONS_API"

    Exemple 3 : Synchronisation locale de données au sein d'une même base

    Exemple d'un "select" source mettant en forme des données, et d'une table destination synchronisée sur celles-ci :

    unicaen-db-import.global.php

    return [
        'import' => [
            'synchros' => [
                [
                    'name' => "SYNCHRO_LOCALE_ROLE",
                    'source' => [
                        'code'               => 'app',
                        'select'             => 'SELECT CODE, LIBELLE, DESCRIPTION FROM SRC_ROLE',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'CODE',
                    ],
                    'destination' => [
                        'code'               => 'Table ROLE',
                        'table'              => 'ROLE',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'CODE',
                    ],
                ],
            ],
        ],
    ];

    Ligne de commande :

    php public/index.php run synchro --name "SYNCHRO_LOCALE_UTILISATEUR"

    Une autre solution (préférable) consisterait à écrire une vue qui réaliserait la mise en forme en question et à utiliser cette fois le paramètre table (au lieu du paramètre select).

    Exemple 4 : Synchronisation à partir d'une source externe

    Exemple 4.1 : Source externe de type base de données

    Cet exemple sera probablement l'une des utilisations les plus fréquentes de ce module.

    Par exemple, vous avez accès à une base de données contenant des utilisateurs et la base de données de votre application possédant ses propres utilisateurs. Vous souhaitez alors synchroniser vos utilisateurs avec ceux disponibles dans l'autre base.

    unicaen-db-import.global.php

    return [
        'import' => [
            'synchros' => [
                [
                    'name' => "SYNCHRO_BDD_EXTERNE",
                    'source' => [
                        'code'               => 'UTILISATEUR_OCTOPUS',
                        'select'             => 'SELECT CODE, NOM, PRENOM, NAISSANCE FROM UTILISATEUR',
                        'connection'         => 'orm_B',
                        'source_code_column' => 'CODE',
                    ],
                    'destination' => [
                        'code'               => 'Table UTILISATEUR',
                        'table'              => 'UTILISATEUR',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'CODE',
                        
                        'intermediate_table' => 'NOM_QUE_JE_FORCE', // sinon ce sera 'TMP_UTILISATEUR'
                        'intermediate_table_auto_drop' => true, // supprime la table intermédiaire si elle existe déjà
    
                    ],
                ],
            ],
        ],
    ];

    Ligne de commande :

    php public/index.php run synchro --name "SYNCHRO_BDD_EXTERNE"

    Une synchronisation de données à partir d'une autre base de données fait en réalité appel successivement au mécanisme d'import et au mécanisme de synchronisation (voir Fonctionnement) ; d'où la présence des paramètres facultatifs intermediate_table et intermediate_table_auto_drop.

    Fonctionne également en spécifiant une 'table' au lieu d'un 'select' dans la source.

    Exemple 4.2 : Source externe de type API

    unicaen-db-import.global.php

    return [
        'import' => [
            'synchros' => [
                [
                    'name' => "SYNCHRO_COMMUNES",
                    'source' => [
                        'code'               => 'geo_api', // DOIT correspondre à un `CODE` de la table `SOURCE`
                        'select'             => '/departements/63/communes?fields=nom,code',
                        'connection'         => 'geo',
                        'source_code_column' => 'code',
                    ],
                    'destination' => [
                        'code'               => 'Table locale',
                        'table'              => 'REGION',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'CODE',
    
                        'intermediate_table_auto_drop' => true,
                    ],
                ],
            ],
        ],
    ];

    Terminal du serveur

    php public/index.php run synchro --name "SYNCHRO_COMMUNES"

    Exemple 5 : Synchronisation de données externes avec récupération des clés étrangères

    De nombreux cas d'utilisation suivront cet exemple.

    Si vous observez les tables exemples évoquées au début de cette section Exemples, vous pourrez constater que les formations possèdent des clés étrangères vers les composantes.

    Pour gérer le cas de ces clés étrangères, il vous faudra :

    • Configurer un import de la base source externe vers une table destination "intermédiaire" ;
    • Créer une vue (conventionnellement préfixée par SRC_) puisant dans la table intermédiaire et réalisant les jointures nécessaires à l'alimentation des clés étrangères ;
    • Configurer un mécanisme de synchro de la vue (source) vers la table destination finale.

    Voici l'exemple d'une vue SRC_FORMATION puisant dans la table intermédiaire TMP_FORMATION et mettant en forme les données qui seront la source de la synchronisation vers la table finale FORMATION :

    CREATE VIEW SRC_FORMATION AS
        SELECT
            tmp.ID   AS ID,
            tmp.CODE AS CODE,
            tmp.NOM  AS NOM,
            c.ID     AS COMPOSANTE_ID
        FROM
            TMP_FORMATION tmp
        INNER JOIN COMPOSANTE c ON tmp.COMPOSANTE_CODE = c.CODE;

    unicaen-db-import.global.php

    return [
        'import' => [
            'imports' => [
                [
                    'name' => "IMPORT_PRÉALABLE", // Importation des données externes dans une table intermédiaire
                    'source' => [
                        'code'               => 'FORMATION_FCA',
                        'select'             => 'SELECT ID, CODE, NOM, COMPOSANTE_CODE FROM FORMATION',
                        'connection'         => 'orm_B',
                        'source_code_column' => 'ID',
                    ],
                    'destination' => [
                        'code'               => 'Table TMP_FORMATION locale',
                        'table'              => 'TMP_FORMATION',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'ID',
                    ],
                ],
            ],
            'synchros' => [
                [
                    'name' => "SYNCHRO_FINALE", // Synchro des données mise en forme vers la table finale
                    'source' => [
                        'code'               => 'TABLE SRC_FORMATION DE MA BASE A UTILISANT TMP_FORMATION',
                        'select'             => 'SELECT * FROM SRC_FORMATION',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'ID',
                    ],
                    'destination' => [
                        'code'               => 'TABLE FORMATION DE MA BASE A',
                        'table'              => 'FORMATION',
                        'connection'         => 'orm_A',
                        'source_code_column' => 'ID',
                    ],
                ],
            ],
        ],
    ];

    Ligne de commande :

    php public/index.php run import --name "IMPORT_PRÉALABLE"
    php public/index.php run synchro --name "SYNCHRO_FINALE"

    Dans cet exemple, la table intermédiaire TMP_FORMATION doit être préalablement créée par vos soins.

    Développement

    Supporter une plateforme de base de données supplémentaire

    Imaginons que l'on veuille ajouter la possibilité d'importer/synchroniser vers une table destination se trouvant sur la plateforme de base de données Oracle.

    Voici ce qu'il faudra faire...

    • Ajouter un fichier de config config/oracle.config.php dans lequel sera spécifié :

      • La classe de "code generator" (que vous devrez fournir) à utiliser pour la plateforme de base de données Oracle (clé code_generators_mapping).

      • La factory (que vous devrez fournir) à utiliser pour instancier le "code generator" en question (clé code_generators_factories).

        Exemple :

        return [
            'import' => [
                'code_generators_mapping' => [
                    \Doctrine\DBAL\Platforms\OraclePlatform::class => \UnicaenDbImport\CodeGenerator\Oracle\CodeGenerator::class,
                ],
                'code_generators_factories' => [
                    \UnicaenDbImport\CodeGenerator\Oracle\CodeGenerator::class => \UnicaenDbImport\CodeGenerator\Oracle\CodeGeneratorFactory::class,
                ],
            ],
        ];
    • Créer un sous-répertoire Oracle dans le répertoire src/UnicaenDbImport/CodeGenerator dans lequel il faudra créer les fichiers/classes suivants :

      .
      ├── Helper
      │   ├── LogTableHelper.php
      │   ├── TableHelper.php
      │   └── TableValidationHelper.php
      ├── CodeGenerator.php
      ├── CodeGeneratorFactory.php
      ├── HelperAbstractFactory.php
    • Respecter les contraintes suivantes pour écrire la classe CodeGenerator :

      • Hériter de la classe abstraite \UnicaenDbImport\CodeGenerator\CodeGenerator.

      • Instancier dans le constructeur la plateforme de base de données à laquelle sera en partie déléguée la génération de code SQL.

        NB: l'instance de la plateforme de base de données injectée ici est utilisée pour générer du SQL compris par la base de données destination. Si aucune classe de plateforme ne correspond exactement à la version de la base de données destination, prenez la plus générique (ex: MySqlPlatform plutôt que MySQL80Platform).

      • Redéfinir si besoin les méthodes de la classe mère qui ne génèreraient pas du code SQL valide pour la plateforme de base de données (ici, Oracle).

        Exemple :

        namespace UnicaenDbImport\CodeGenerator\Oracle;
        
        use Doctrine\DBAL\Platforms\OraclePlatform;
        
        class CodeGenerator extends \UnicaenDbImport\CodeGenerator\CodeGenerator
        {
            public function __construct()
            {
                $this->platform = new OraclePlatform();
            }
        
            public function generateSQLForIntermmediateTableDrop($tableName)
            {
                return "DROP TABLE $tableName CASCADE CONSTRAINTS ;";
            }
        }
    • Respecter les contraintes suivantes pour écrire le "helper" de génération de code Helper\TableHelper :

      • Hériter obligatoirement de la classe abstraite \UnicaenDbImport\CodeGenerator\Helper\TableHelper ; et donc définir les méthodes abstraites de la classe mère.

      • Instancier dans le constructeur la plateforme de base de données à laquelle sera en partie déléguée la génération de code SQL.

      • Redéfinir si besoin les méthodes de la classe mère qui ne génèreraient pas du code SQL valide pour la plateforme de base de données (ici, Oracle).

        Exemple :

        namespace UnicaenDbImport\CodeGenerator\Oracle\Helper;
        
        use Doctrine\DBAL\Platforms\OraclePlatform;
        
        class TableHelper extends \UnicaenDbImport\CodeGenerator\Helper\TableHelper
        {
            /**
             * @var OraclePlatform
             */
            protected $platform;
        
            public function __construct()
            {
                $this->platform = new OraclePlatform();
            }
        
            protected function generateDiffViewDeletionSQLSnippet($destinationTable)
            {
                $name = $this->generateDiffViewName($destinationTable);
        
                return "DROP VIEW $name";
            }
          
            //...
        
        }
    • Respecter les mêmes contraintes dans les autres helpers : Helper\LogTableHelper, Helper\TableValidationHelper.

    • Respecter les contraintes suivantes pour écrire la factory CodeGeneratorFactory :

      • Injecter dans le "code generator" une instance de la plateforme correspondant à la base de données destination.

        NB: l'instance de la plateforme de base de données injectée ici est utilisée pour générer du SQL compris par la base de données destination. Si aucune classe de plateforme ne correspond exactement à la version de la base de données destination, prenez la plus générique (ex: MySqlPlatform plutôt que MySQL80Platform)

      • Injecter aussi les instances des helpers évoqués plus haut, obtenus auprès du container.

        Exemple :

        namespace UnicaenDbImport\CodeGenerator\Oracle;
        
        use Psr\Container\ContainerInterface;
        use UnicaenDbImport\Config\Config;
        
        class CodeGeneratorFactory
        {
            /**
             * @param ContainerInterface $container
             * @return CodeGenerator
             */
            public function __invoke(ContainerInterface $container)
            {
                /** @var Config $config */
                $config = $container->get(Config::class);
        
                $tableHelper = $container->get(Helper\TableHelper::class);
                $tableValidationHelper = $container->get(Helper\TableValidationHelper::class);
                $logTableHelper = $container->get(Helper\LogTableHelper::class);
        
                $codeGenerator = new CodeGenerator();
                $codeGenerator->setConfig($config);
                $codeGenerator->setTableHelper($tableHelper);
                $codeGenerator->setTableValidationHelper($tableValidationHelper);
                $codeGenerator->setLogTableHelper($logTableHelper);
        
                return $codeGenerator;
            }
        }