/* ============================================================ */ /* Nom de la base : TREE */ /* Nom de SGBD : InterBase 6 */ /* Date de cr‚ation : 07/11/2003 10:38 */ /* ============================================================ */ /* ============================================================ */ /* Table : T_NOMENCLATURE_NMC */ /* ============================================================ */ create table T_NOMENCLATURE_NMC ( NMC_ID INTEGER not null, NMC_NOM VARCHAR(32) , NMC_BG INTEGER not null, NMC_BD INTEGER not null, NMC_NIVEAU INTEGER not null, constraint PK_T_NOMENCLATURE_NMC primary key (NMC_ID) ); /* ============================================================ */ /* Index : IDX_BG */ /* ============================================================ */ create ASC index IDX_BG on T_NOMENCLATURE_NMC (NMC_BG); /* ============================================================ */ /* Index : IDX_BD */ /* ============================================================ */ create ASC index IDX_BD on T_NOMENCLATURE_NMC (NMC_BD); /* ============================================================ */ /* Index : IDX_NIV */ /* ============================================================ */ create ASC index IDX_NIV on T_NOMENCLATURE_NMC (NMC_NIVEAU); /* ============================================================ */ /* générateur pour incrément clef table nomenclature */ /* ============================================================ */ CREATE GENERATOR GEN_ID_NMC; /* ============================================================ */ /* gestion des erreurs */ /* ============================================================ */ CREATE EXCEPTION ERR_TREE_DELETE 'Erreur dans la procédure de suppression dans l''arbre'; CREATE EXCEPTION ERR_TREE_INSERT 'Erreur dans la procédure d''insertion dans l''arbre'; CREATE EXCEPTION ERR_TREE_MOVE 'Erreur dans la procédure de déplacement dans l''arbre'; /* ============================================= */ /* PROCÉDURE STOCKÉE */ /* ============================================= */ /* SUPPRESSION DANS L'ARBRE DES NOMENCLATURES */ /* ============================================= */ COMMIT WORK; SET AUTODDL OFF; SET TERM ^ ; /* Stored procedures */ CREATE PROCEDURE "SP_DEL_TREE_NMC" ( "ID" INTEGER, "RECURS" SMALLINT ) AS BEGIN EXIT; END ^ ALTER PROCEDURE "SP_DEL_TREE_NMC" ( "ID" INTEGER, "RECURS" SMALLINT ) AS /* variable de test */ DECLARE VARIABLE OK INTEGER; /* Informations sur l'élément à supprimer */ DECLARE VARIABLE bg INTEGER; DECLARE VARIABLE bd INTEGER; DECLARE VARIABLE delta INTEGER; BEGIN /* Contrôle des paramètres */ IF ((:ID IS NULL) OR (:RECURS IS NULL)) THEN EXCEPTION ERR_TREE_DELETE; /* L'élément existe toujours ? */ SELECT count(*) FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id INTO :OK; IF ((:OK IS NULL) OR (:OK <> 1)) THEN EXCEPTION ERR_TREE_DELETE; /* récupération des éléments du noeud à supprimer */ SELECT NMC_BG, NMC_BD FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id INTO :bg, :bd; IF (:RECURS = 1) THEN BEGIN /*:::::::::::::::::::::::::::::::::::*/ /* Suppression de tout le sous arbre */ /*:::::::::::::::::::::::::::::::::::*/ /* Calcul du delta */ delta = bd - bg + 1; /* suppression des noeuds du sous arbre */ DELETE FROM T_NOMENCLATURE_NMC WHERE NMC_BG >= :bg AND NMC_BD <= :bd; /* décalage à gauche des bornes gauche des noeuds à droite des éléments supprimés */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - :delta WHERE NMC_BG > :bd; /* décalage à gauche des bornes droites des noeuds à droite des éléments supprimés */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD - :delta WHERE NMC_BD > :bd; END ELSE BEGIN /*:::::::::::::::::::::::::::::::::::*/ /* Suppression de l'élément seul */ /*:::::::::::::::::::::::::::::::::::*/ /* suppression de l'élément */ DELETE FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id; /* réajustement du sous arbre sous l'élément supprimé */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - 1, NMC_BD = NMC_BD - 1, NMC_NIVEAU = NMC_NIVEAU - 1 WHERE NMC_BG > :bg AND NMC_BD < :bd; /* décalage à gauche des bornes gauche des noeuds à droite des éléments supprimés */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - 2 WHERE NMC_BG > :bd; /* décalage à gauche des bornes droites des noeuds à droite des éléments supprimés */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD - 2 WHERE NMC_BD > :bd; END END ^ SET TERM ; ^ COMMIT WORK; SET AUTODDL ON; /* ======================================= */ /* PROCÉDURE STOCKÉE */ /* ======================================= */ /* INSERTION DANS L'ARBRE DES NOMENCLATURE */ /* ======================================= */ COMMIT WORK; SET AUTODDL OFF; SET TERM ^ ; /* Stored procedures */ CREATE PROCEDURE "SP_TREE_NMC_INSERT" ( "ID_PARENT" INTEGER, "MODE" CHAR(2), "LIB" VARCHAR(32) ) RETURNS ( "I" INTEGER ) AS BEGIN EXIT; END ^ ALTER PROCEDURE "SP_TREE_NMC_INSERT" ( "ID_PARENT" INTEGER, "MODE" CHAR(2), "LIB" VARCHAR(32) ) RETURNS ( "I" INTEGER ) AS /* variable de test */ DECLARE VARIABLE OK INTEGER; /* dernière clef insérée */ DECLARE VARIABLE id INTEGER; /* Informations du parent */ DECLARE VARIABLE bgp INTEGER; DECLARE VARIABLE bdp INTEGER; DECLARE VARIABLE nivp INTEGER; /* Informations de l'élément inséré */ DECLARE VARIABLE bgi INTEGER; DECLARE VARIABLE bdi INTEGER; DECLARE VARIABLE nivi INTEGER; BEGIN /* Contrôle des paramètres */ IF ((:mode IS NULL) OR (:lib IS NULL) OR (:lib = '')) THEN EXCEPTION ERR_TREE_INSERT; mode = UPPER(mode); /* vérification de l'existence du mode d'insertion */ IF (NOT ( :mode = 'FA' OR :mode = 'FC' OR :mode = 'GF' OR :mode = 'PF' OR :mode = 'P ')) THEN EXCEPTION ERR_TREE_INSERT; /* cas particulier : insertion de la racine de l'arbre */ IF (:id_parent IS NULL) THEN BEGIN /* vérification : pas de ligne dans la table, et mode = 'P' */ SELECT count(*) FROM T_NOMENCLATURE_NMC INTO :OK; IF ((:OK <> 0) OR (:OK IS NOT NULL) OR (:mode <> 'P')) THEN EXCEPTION ERR_TREE_INSERT; /* calcul des paramètres d'insertion du noeud */ bgi = 1; bdi = 2; nivi = 0; END ELSE BEGIN /* vérification de l'existence du parent */ SELECT count(*) FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id_parent INTO :OK; /* plusieurs parent ou 0 n'est pas bon signe ! IF OK <> 1 THEN EXCEPTION ERR_TREE_INSERT; /* tout est OK, les insertions sont possibles */ /* On récupère les éléments du parent */ SELECT NMC_BG, NMC_BD, NMC_NIVEAU FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id_parent INTO :bgp, :bdp, :nivp; END /* Insertion en Grand Frère GF */ IF (:mode = 'GF') THEN BEGIN /* décalage Limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD > :bgp; /* décalage Limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG >= :bgp; /* calcul des paramètres d'insertion du noeud */ bgi = bgp; bdi = bgp + 1; nivi = nivp; END /* Insertion en Petit Frère PF */ IF (mode = 'PF') THEN BEGIN /* décalage Limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD > :bdp; /* décalage Limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG >= :bdp; /* calcul des paramètres d'insertion du noeud */ bgi = bdp + 1; bdi = bdp + 2; nivi = nivp; END /* Insertion en Fils ainé */ IF (mode = 'FA') THEN BEGIN /* décalage Limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD > :bgp; /* décalage Limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG > :bgp; /* calcul des paramètres d'insertion du noeud */ bgi = bgp + 1; bdi = bgp + 2; nivi = nivp + 1; END /* Insertion en Fils cadet */ IF (mode = 'FC') THEN BEGIN /* décalage Limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD >= :bdp; /* décalage Limite inferieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG > :bdp; /* calcul des paramètres d'insertion du noeud */ bgi = bdp; bdi = bdp + 1; nivi = nivp + 1; END /* insertion effective du noeud */ id = GEN_ID(GEN_ID_NMC, 1); INSERT INTO T_NOMENCLATURE_NMC ( NMC_ID, NMC_NOM, NMC_NIVEAU, NMC_BG, NMC_BD ) VALUES ( :id, :lib, :nivi, :bgi, :bdi ); i = id; WHEN ANY DO i = -1; END ^ SET TERM ; ^ COMMIT WORK; SET AUTODDL ON; /* =============================================== */ /* PROCÉDURE STOCKÉE */ /* =============================================== */ /* DÉPLACEMENT D'UN SOUS ARBRE DANS NOMENCLATURE */ /* =============================================== */ COMMIT WORK; SET AUTODDL OFF; SET TERM ^ ; /* Stored procedures */ CREATE PROCEDURE "SP_MOVE_TREE_NMC" ( "ID" INTEGER, "ID_PARENT" INTEGER, "MODE" CHAR(2), "RECURS" INTEGER ) AS BEGIN EXIT; END ^ ALTER PROCEDURE "SP_MOVE_TREE_NMC" ( "ID" INTEGER, "ID_PARENT" INTEGER, "MODE" CHAR(2), "RECURS" INTEGER ) AS /* teste l'existence des éléments */ DECLARE VARIABLE OK INTEGER; /* limite supérieure droite de l'arborescence */ DECLARE VARIABLE bdmax INTEGER; /* Delta de borne */ DECLARE VARIABLE deltab INTEGER; /* information du noeud déplacé */ DECLARE VARIABLE bgd INTEGER; DECLARE VARIABLE bdd INTEGER; DECLARE VARIABLE nivd INTEGER; /* information du noeud parent */ DECLARE VARIABLE bgp INTEGER; DECLARE VARIABLE bdp INTEGER; DECLARE VARIABLE nivp INTEGER; BEGIN /* les paramètres ne peuvent être nuls */ IF ((:MODE IS NULL) OR (:RECURS IS NULL) OR (:ID IS NULL) OR (:ID_PARENT IS NULL)) THEN EXCEPTION ERR_TREE_MOVE; /* recurs ne peut prendre que les valeurs 0 (non) ou 1 (oui) */ IF ((:RECURS <> 0) AND (:RECURS <> 1)) THEN EXCEPTION ERR_TREE_MOVE; /* source du déplacement = cible du déplacement : situation idiote */ IF (:ID = :ID_PARENT) THEN EXCEPTION ERR_TREE_MOVE; /* L'élément existe toujours ? */ SELECT count(*) FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id INTO :OK; IF ((:OK IS NULL) OR (:OK <> 1)) THEN EXCEPTION ERR_TREE_MOVE; /* Le parent existe toujours ? */ SELECT count(*) FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id_parent INTO :OK; IF ((:OK IS NULL) OR (:OK <> 1)) THEN EXCEPTION ERR_TREE_MOVE; /****************************************************************/ /* Les vérifications sont faites, tout va bien, on récupère les */ /* paramètres nécessaire au déplacement de l'arbre */ /****************************************************************/ /* On récupère la borne supérieure max de l'ensemble */ SELECT max(NMC_BD) FROM T_NOMENCLATURE_NMC INTO :bdmax; /* On récupère les caractéristiques du noeud à déplacer */ SELECT NMC_BG, NMC_BD, NMC_NIVEAU FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id INTO :bgd, :bdd, :nivd; /* déplacement de la racine avec recurs : situation idiote */ IF ((:RECURS = 1) AND (:nivd = 0)) THEN EXCEPTION ERR_TREE_MOVE; /* vérification de l'exitence du mode de déplacement */ mode = UPPER(mode); IF (NOT ( (:mode = 'GF') OR (:mode = 'PF') OR (:mode = 'FC') OR (:mode = 'FA') )) THEN EXCEPTION ERR_TREE_MOVE; /* calcul du delta de décalage */ deltab = bdmax + 1 - bgd; /* DEBUT de l'opération proprement dite... */ /* Opération récursive ou non ? */ IF (:recurs = 0) THEN BEGIN /*********************************************************/ /* pas de récursivité : seul l'élément doit être déplacé */ /*********************************************************/ /* écartement des bornes de l'arbre vers la fin de liste */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + :deltab, NMC_BD = NMC_BD + :deltab WHERE NMC_ID = :id; /* remontée des descendants du noeud mouvementé dans la hiérarchie */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - 1, NMC_BD = NMC_BD - 1, NMC_NIVEAU = NMC_NIVEAU - 1 WHERE NMC_BG > :bgd AND NMC_BD < :bdd; /* rééquilibrage de l'arbre côté gauche */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - 2 WHERE NMC_BG > :bdd AND NMC_BG < :bdmax; /* rééquilibrage de l'arbre côté droit */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD - 2 WHERE NMC_BD > :bdd AND NMC_BD <= :bdmax; /* récupèration des caractéristiques de la cible du déplacement */ SELECT NMC_BG, NMC_BD, NMC_NIVEAU FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id_parent INTO :bgp, :bdp, :nivp; /*::::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en grand frère de l'élément seul */ /*::::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'GF') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD >= :bdp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG >= :bgp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'élément déplacé */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = :bgp, NMC_BD = :bgp + 1, NMC_NIVEAU = :nivp WHERE NMC_ID = :id; END /*::::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en petit frère de l'élément seul */ /*::::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'PF') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD > :bdp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG > :bdp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'élément déplacé */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = :bdp + 1, NMC_BD = :bdp + 2, NMC_NIVEAU = :nivp WHERE NMC_ID = :id; END /*::::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en fils cadet de l'élément seul */ /*::::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'FC') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD >= :bdp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG > :bdp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'élément déplacé */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = :bdp, NMC_BD = :bdp + 1, NMC_NIVEAU = :nivp + 1 WHERE NMC_ID = :id; END /*::::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en fils ainé de l'élément seul */ /*::::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'FA') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + 2 WHERE NMC_BD > :bgp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + 2 WHERE NMC_BG > :bgp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'élément déplacé */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = :bgp + 1, NMC_BD = :bgp + 2, NMC_NIVEAU = :nivp + 1 WHERE NMC_ID = :id; END END ELSE BEGIN /*********************************************************/ /* récursivité : tout le sous arbre doit être déplacé */ /*********************************************************/ /* déplacement de l'élément et de sa descendance en fin d'arbre */ /* Le niveau sera réactualisé ultérieurement */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + :deltab, NMC_BD = NMC_BD + :deltab, NMC_NIVEAU = NMC_NIVEAU - :nivd WHERE NMC_BG >= :bgd AND NMC_BD <= :bdd; /* rétablissement des bornes */ /* Calcul du Delta */ deltab = bdd - bgd + 1; /* décalage de l'arbre à droite */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD - :deltab WHERE NMC_BD > :bdd AND NMC_BG <= :bdmax; /* décalage de l'arbre à gauche */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - :deltab WHERE NMC_BG > :bdd AND NMC_BG < :bdmax; /* récupération des caractéristiques du parent */ SELECT NMC_BG, NMC_BD, NMC_NIVEAU FROM T_NOMENCLATURE_NMC WHERE NMC_ID = :id_parent INTO :bgp, :bdp, :nivp; /*:::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en grand frère du sous arbre */ /*:::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'GF') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + :deltab WHERE NMC_BD > :bgp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + :deltab WHERE NMC_BG >= :bgp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'arbre déplacé */ deltab = bdmax - bgp + 1; UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - :deltab, NMC_BD = NMC_BD - :deltab, NMC_NIVEAU = NMC_NIVEAU + :nivp WHERE NMC_BG > :bdmax; END /*:::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en petit frère du sous arbre */ /*:::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'PF') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + :deltab WHERE NMC_BD > :bdp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + :deltab WHERE NMC_BG > :bdp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'arbre déplacé */ deltab = bdmax - bdp; UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - :deltab, NMC_BD = NMC_BD - :deltab, NMC_NIVEAU = NMC_NIVEAU + :nivp WHERE NMC_BG > :bdmax; END /*:::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en fils cadet du sous arbre */ /*:::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'FC') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + :deltab WHERE NMC_BD >= :bdp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + :deltab WHERE NMC_BG > :bdp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'arbre déplacé */ deltab = bdmax - bdp + 1; UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - :deltab, NMC_BD = NMC_BD - :deltab, NMC_NIVEAU = NMC_NIVEAU + :nivp + 1 WHERE NMC_BG > :bdmax; END /*:::::::::::::::::::::::::::::::::::::::::::*/ /* insertion en fils ainé du sous arbre */ /*:::::::::::::::::::::::::::::::::::::::::::*/ IF (:mode = 'FA') THEN BEGIN /* déplacement de la limite supérieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BD = NMC_BD + :deltab WHERE NMC_BD > :bgp AND NMC_BD <= :bdmax; /* déplacement de la limite inférieure */ UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG + :deltab WHERE NMC_BG > :bgp AND NMC_BG < :bdmax; /* mise à jour des bornes de l'arbre déplacé */ deltab = bdmax - bgp; UPDATE T_NOMENCLATURE_NMC SET NMC_BG = NMC_BG - :deltab, NMC_BD = NMC_BD - :deltab, NMC_NIVEAU = NMC_NIVEAU + :nivp + 1 WHERE NMC_BG > :bdmax; END END END ^ SET TERM ; ^ COMMIT WORK; SET AUTODDL ON;