PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : Migration » ora2pg - DDL non-traduits » 15/10/2015 11:52:57

Bonjour,

Un grand merci pour votre réactivité : j'ai downloadé et testé la dernière version sur github, et mes triggers problématiques migrent maintenant parfaitement.
Cordialement,

#2 Migration » ora2pg - DDL non-traduits » 14/10/2015 16:09:47

Cyrille
Réponses : 2

Je tente actuellement de migrer une base oracle sous postgres en utilisant ora2pg (v15.3), en procédant selon la méthode suivante :


- migration vers des fichiers sql distincts des tables, contraintes, et index
- migration des données vers un fichier sql
- migration des sequences vers un fichier sql
- migration des triggers vers un fichier sql


Et j'importe ensuite dans ma base postgres à partir des différents fichiers sql générés par ora2pg :
- les tables
- les sequences
- les données
- les contraintes
- les index
- les triggers


Tout se passe sans soucis, jusqu'à l'import des triggers.
Quand je joue le fichier sql sur ma base postgres, j'obtiens la sortie suivante :

SET
NOTICE:  trigger "auth_group_permissions_tr" for table "auth_group_permissions" does not exist, skipping
DROP TRIGGER
CREATE FUNCTION
ERROR:  relation "AUTH_GROUP_PERMISSIONS" does not exist

Si je passe ON_ERROR_STOP à OFF et que je relance, j'obtiens une erreur du même type sur la totalité des CREATE FUNCTION.
En regardant le code sql généré, je me rends compte qu'il n'a pas été traduit par ora2pg. Par exemple, pour le premier trigger du fichier ("auth_group_permissions_tr"), on trouve le code suivant :

DROP TRIGGER IF EXISTS auth_group_permissions_tr ON auth_group_permissions CASCADE;
CREATE OR REPLACE FUNCTION trigger_fct_auth_group_permissions_tr () RETURNS trigger AS $BODY$
BEGIN
        SELECT "AUTH_GROUP_PERMISSIONS_SQ".nextval
        INTO NEW."ID" ;
    RETURN NEW;
END
$BODY$
 LANGUAGE 'plpgsql';


CREATE TRIGGER "AUTH_GROUP_PERMISSIONS_TR"
BEFORE INSERT ON "AUTH_GROUP_PERMISSIONS"
FOR EACH ROW


        WHEN (new."ID" IS NULL)
        EXECUTE PROCEDURE trigger_fct_auth_group_permissions_tr();

C'est le même principe pour tous les triggers du fichier : des noms de tables ou de colonnes entre guillemets et en majuscules, des netxval
façon oracle, des IS NULL...


Quand je regarde le DDL directement côté oracle, je trouve le code suivant :

SQL> select dbms_metadata.get_ddl('TRIGGER','AUTH_GROUP_PERMISSIONS_TR','CUBE_PGSQL') from DUAL;


DBMS_METADATA.GET_DDL('TRIGGER','AUTH_GROUP_PERMISSIONS_TR','CUBE_PGSQL')
--------------------------------------------------------------------------------


  CREATE OR REPLACE TRIGGER "CUBE_PGSQL"."AUTH_GROUP_PERMISSIONS_TR"
BEFORE INSERT ON "AUTH_GROUP_PERMISSIONS"
FOR EACH ROW
  WHEN (new."ID" IS NULL) BEGIN
        SELECT "AUTH_GROUP_PERMISSIONS_SQ".nextval
        INTO :new."ID" FROM dual;
    END;
ALTER TRIGGER "CUBE_PGSQL"."AUTH_GROUP_PERMISSIONS_TR" ENABLE

En comparant avec une autre base oracle migrée précédemment sur le même principe (et sans la moindre erreur sur les triggers), je
me rends compte que sur cette dernière, les DDL des triggers ne contenaient pas de guillemets. Je fais donc un test en créant sur
ma base un trigger sur le modèle de AUTH_GROUP_PERMISSIONS_TR, en enlevant tous les guillemets :

SQL> CREATE TRIGGER AUTH_GROUP_PERMISSIONS_TR_TEST
BEFORE INSERT ON AUTH_GROUP_PERMISSIONS
  2    3  FOR EACH ROW
  4    WHEN (new.ID IS NULL) BEGIN
  5          SELECT AUTH_GROUP_PERMISSIONS_SQ.nextval
  6          INTO :new.ID FROM dual;
  7      END;
  8  /

ALTER TRIGGER AUTH_GROUP_PERMISSIONS_TR_TEST ENABLE;

Je vérifie le DDL :

SQL> select dbms_metadata.get_ddl('TRIGGER','AUTH_GROUP_PERMISSIONS_TR_TEST','CUBE_PGSQL') from DUAL;

DBMS_METADATA.GET_DDL('TRIGGER','AUTH_GROUP_PERMISSIONS_TR_TEST','CUBE_PGSQL')
--------------------------------------------------------------------------------

  CREATE OR REPLACE TRIGGER "CUBE_PGSQL"."AUTH_GROUP_PERMISSIONS_TR_TEST"
BEFORE INSERT ON AUTH_GROUP_PERMISSIONS
FOR EACH ROW
   WHEN (new.ID IS NULL) BEGIN
        SELECT AUTH_GROUP_PERMISSIONS_SQ.nextval
        INTO :new.ID FROM dual;
    END;
ALTER TRIGGER "CUBE_PGSQL"."AUTH_GROUP_PERMISSIONS_TR_TEST" ENABLE

Si j'utilise ensuite ora2pg pour exporter uniquement ce nouveau trigger vers un fichier sql (TYPE TRIGGER et ALLOW AUTH_GROUP_PERMISSIONS_TR_TEST), j'obtiens le fichier suivant :

[postgres@****** IND_DEV]$ cat triggers_testcb_IND_DEV.sql
-- Generated by Ora2Pg, the Oracle database Schema converter, version 15.3
-- Copyright 2000-2015 Gilles DAROLD. All rights reserved.
-- DATASOURCE: dbi:Oracle:IND_DEV


SET client_encoding TO 'UTF8';


\set ON_ERROR_STOP ON


DROP TRIGGER IF EXISTS auth_group_permissions_tr_test ON auth_group_permissions CASCADE;
CREATE OR REPLACE FUNCTION trigger_fct_auth_group_permissions_tr_test () RETURNS trigger AS $BODY$
BEGIN
        SELECT nextval('auth_group_permissions_sq')
        INTO NEW.ID ;
    RETURN NEW;
END
$BODY$
 LANGUAGE 'plpgsql' SECURITY DEFINER;
-- REVOKE ALL ON FUNCTION trigger_fct_auth_group_permissions_tr_test FROM PUBLIC;


CREATE TRIGGER AUTH_GROUP_PERMISSIONS_TR_TEST
BEFORE INSERT ON AUTH_GROUP_PERMISSIONS
FOR EACH ROW


        WHEN (coalesce(new.ID::text, '') = '')
        EXECUTE PROCEDURE trigger_fct_auth_group_permissions_tr_test();


[postgres@***** IND_DEV]$

Le code en question correspond à ce que j'attendais, et joué sur ma base postgres, il crée bien le trigger.


Il semble donc que ora2pg ne peut pas traduire le DDL d'un trigger (et probablement d'autres objets) si ce
dernier a été créé en utilisant des guillemets et des noms en majuscules (tables, colonnes, etc...).


Un workaround possible serait :
- exporter tous les triggers avec expdp, et les importer dans un fichier sql via impdp
- passer un coup de sed sur le fichier en question pour supprimer les guillemets
- fournir le fichier en question en input à ora2pg pour le laisser traduire ca en code sql postgres


Le problème, c'est que ora2pg ne semble pas être prévu pour faire ça : les commentaires associés au paramètre INPUT_FILE disent
clairement "This can only be used with the following export type: PROCEDURE, FUNCTION or PACKAGE." (j'ai bien essayé de lui passer
quand même un fichier avec les DDL oracle de mes triggers, dont j'avais supprimé les guillemets, et ca n'a effectivement pas marché...).


Une autre solution serait de corriger les DDL au niveau de la base oracle, mais à moins de supprimer/re-créer tous les triggers (ce
que je préférerais éviter), je ne vois pas vraiment comment...


Si quelqu'un a une solution ou un contournement, je lui assure d'avance toute ma gratitude : je commence un peu à m'arracher les
cheveux à ce stade. smile

Pied de page des forums

Propulsé par FluxBB