CREATE FUNCTION SUPPORT_DISTANCE_COHERENCE_INSERT_FN()
RETURNS TRIGGER AS
$le_trigger$
DECLARE Erreur VARCHAR ;
DECLARE theKount INTEGER ;
DECLARE theCumulDistanceAntecedent INTEGER ;
DECLARE theCumulDistanceSuccesseur INTEGER ;
DECLARE thePredecesseur INTEGER ;
DECLARE theSuccesseur INTEGER ;
DECLARE theSupportDebut INTEGER ;
DECLARE theSupportAcreer INTEGER ;
DECLARE theSensParcours VARCHAR ;
BEGIN
Erreur = '' ;
RAISE INFO USING MESSAGE = TG_OP || ' -------- nouvel ' || TG_OP || ' -------------' ;
-- --------------------------------------------------------------------------------------------
-- On compte le nombre de supports déjà existants pour la ligne concernée
-- --------------------------------------------------------------------------------------------
theKount = (SELECT COUNT(*) FROM SUPPORT WHERE LigneId = NEW.LigneId) ;
RAISE INFO USING MESSAGE = TG_OP || ', theKount = ' || theKount ;
-- --------------------------------------------------------------------------------------------
-- On commence par traiter le cas où la table ne contient aucun support pour la ligne concernée :
-- Cézigue ajoute un 1er support. Partons du principe que sa distance cumulée doit être égale à 0.
-- Si c'est le cas, comme on ne sait pas encore dans quel sens parcourir les supports (mode
-- ascendant ou descendant, on considère que ce sens est pour le moment inconnu : SensParcours = '?'
-- -----------------------------------------------------------------------------------------
IF theKount = 0 THEN
IF NEW.DistanceCumul > 0 THEN
Erreur = 'SupportNo = '''|| NEW.SupportNo
|| ''' est le 1er support créé pour la ligne '''
|| NEW.LigneId || ''' et doit donc être situé à la distance 0.' ;
RAISE EXCEPTION SQLSTATE '45001' USING MESSAGE = Erreur ;
ELSE
New.SensParcours = '?' ;
RAISE INFO USING MESSAGE = TG_OP || ' NEW.SupportNo = '''
|| NEW.SupportNo || ''' ; New.DistanceCumul = '''
|| New.DistanceCumul || '''.' ;
RETURN NEW ;
END IF ;
END IF ;
---------------------------------------------------------------------------------------
-- 2e support et suivants :
Détermination du prédécesseur (ou successeur) sur la ligne du support
---------------------------------------------------------------------------------------
--------------------------------------------------------------------
-- Y a-t-il un prédécesseur pour le support en cours ?
--------------------------------------------------------------------
thePredecesseur = (SELECT SupportNo
FROM SUPPORT
WHERE SupportNo = (SELECT MAX(SupportNo)
FROM SUPPORT
WHERE SupportNo < NEW.SupportNo
AND SensParcours <> 'desc' -- sinon on interpréterait un 'desc' comme un 'asc'
AND LigneId = New.LigneId)) ;
RAISE INFO USING MESSAGE = TG_OP || ', NEW.SupportNo = ' || NEW.SupportNo ;
RAISE INFO USING MESSAGE = TG_OP || ', thePredecesseur (MAX) = '
|| coalesce(thePredecesseur, -1) ;
--------------------------------------------------------------------------
-- S'il n'y a de prédécesseur, c'est donc qu'il s'agit du successeur
--------------------------------------------------------------------------
IF COALESCE(thePredecesseur, -1) = -1 THEN
thePredecesseur = (SELECT SupportNo
FROM SUPPORT
WHERE SupportNo = (SELECT MIN(SupportNo)
FROM SUPPORT
WHERE SupportNo > NEW.SupportNo
AND LigneId = New.LigneId)) ;
RAISE INFO USING MESSAGE = TG_OP || ', thePredecesseur (MIN) = '
|| coalesce(thePredecesseur, -1) ;
END IF ;
theCumulDistanceAntecedent = (SELECT DistanceCumul
FROM SUPPORT
WHERE SupportNo = thePredecesseur) ;
RAISE INFO USING MESSAGE = TG_OP || ', theCumulDistanceAntecedent = '
|| theCumulDistanceAntecedent ;
-- ------------------------------------------------------------------------------------------
-- On traite du cas où l'on n'a précédemment créé qu'un seul support pour la ligne en cours
-- et où il s'agit d'en insérer un 2e. C'est à ce moment-là qu'on décide du sens de
-- parcours de supports : ascendant ou descendant.
-- ------------------------------------------------------------------------------------------
IF theKount = 1 THEN
theSupportDebut = (SELECT SupportNo
FROM SUPPORT
WHERE LigneId = New.LigneId) ;
RAISE INFO USING MESSAGE = TG_OP || ', New.LigneId = ''' || New.LigneId || ''', theSupportDebut = ' || theSupportDebut ;
theSupportAcreer = New.SupportNo ;
RAISE INFO USING MESSAGE = TG_OP || ', theSupportAcreer = ' || theSupportAcreer ;
IF theSupportAcreer > theSupportDebut
AND New.DistanceCumul > theCumulDistanceAntecedent THEN
New.SensParcours = 'asc' ;
ELSEIF theSupportAcreer < theSupportDebut
AND New.DistanceCumul > theCumulDistanceAntecedent THEN
New.SensParcours = 'desc' ;
ELSE
Erreur = 'La distance cumulée ''' || New.DistanceCumul || ''' du support '''
|| NEW.SupportNo
|| ''' doit être différente de la distance cumulée '''
|| theCumulDistanceAntecedent
|| ''' du support précédent ''' || thePredecesseur || ''' !' ;
RAISE EXCEPTION SQLSTATE '45002' USING MESSAGE = Erreur ;
END IF ;
RAISE INFO USING MESSAGE = TG_OP || ', SensParcours qu''on vient de déterminer : '''
|| New.SensParcours || '''.' ;
-- ------------------------------------------------------------------------------------
-- On met à jour le sens du parcours pour le support de début, qui jusque là valait '?',
-- on ajoute le support et on dégage.
-- -------------------------------------------------------------------------------------
UPDATE SUPPORT
SET SensParcours = New.SensParcours
WHERE LigneId = New.LigneId and SensParcours = '?' ;
RETURN NEW ;
END IF ;
-----------------------------------------------------------------------------------
-- On traite des supports à partir du 3e de la ligne en cours
-----------------------------------------------------------------------------------
New.SensParcours = (SELECT SensParcours
FROM SUPPORT
WHERE LigneId = New.LigneId AND DistanceCumul = 0) ;
RAISE INFO USING MESSAGE = 'New.SensParcours = ' || New.SensParcours ;
theCumulDistanceAntecedent = (SELECT DistanceCumul
FROM SUPPORT
WHERE SupportNo = thePredecesseur) ;
RAISE INFO USING MESSAGE = 'NEW.SupportNo = ' || NEW.SupportNo
|| ', New.DistanceCumul = ' || New.DistanceCumul
|| ', theCumulDistanceAntecedent = '
|| theCumulDistanceAntecedent ;
IF New.SensParcours = 'asc' AND New.DistanceCumul <= theCumulDistanceAntecedent THEN
Erreur = 'La distance cumulée ''' || New.DistanceCumul
|| ''' du support '''|| NEW.SupportNo
|| ''' doit être supérieure à la distance cumulée '''
|| theCumulDistanceAntecedent
|| ''' du support précédent ''' || thePredecesseur || '''.' ;
RAISE EXCEPTION SQLSTATE '45002' USING MESSAGE = Erreur ;
END IF ;
IF New.SensParcours = 'desc' AND New.DistanceCumul <= theCumulDistanceAntecedent THEN
Erreur = 'La distance cumulée ''' || New.DistanceCumul || ''' du support '''
|| NEW.SupportNo
|| ''' doit être supérieure à la distance cumulée '''
|| theCumulDistanceAntecedent
|| ''' du support précédent ''' || thePredecesseur || '''.' ;
RAISE EXCEPTION SQLSTATE '45002' USING MESSAGE = Erreur ;
END IF ;
----------------------------------------------------------------------------------------
-- Dans le sens ascendant, s'il existe des numéros de supports > au numéro du support
-- qu'on crée, la distance cumulée de celui-ci doit être < à la distance cumulée de ces
-- supports ;
-- Dans le sens descendant, s'il existe des numéros de supports < au numéro du support
-- qu'on crée, la distance cumulée de celui-ci doit être < à la distance cumulée de ces
-- supports.
----------------------------------------------------------------------------------------
IF New.SensParcours = 'asc' THEN
theSuccesseur = (SELECT MIN(SupportNo)
FROM SUPPORT
WHERE LigneId = New.LigneId AND SupportNo > New.SupportNo) ;
ELSEIF New.SensParcours = 'desc' THEN
theSuccesseur = (SELECT MAX(SupportNo)
FROM SUPPORT
WHERE LigneId = New.LigneId
AND SupportNo < New.SupportNo) ;
END IF ;
IF COALESCE(theSuccesseur, -1) > -1 THEN
theCumulDistanceSuccesseur = (SELECT DistanceCumul
FROM SUPPORT
WHERE SupportNo = theSuccesseur) ;
IF New.DistanceCumul > theCumulDistanceSuccesseur THEN
RAISE EXCEPTION USING MESSAGE = 'La distance cumulée ''' || New.DistanceCumul
|| ''' du support '''|| NEW.SupportNo
|| ''' doit être inférieure à la distance cumulée '''
|| theCumulDistanceSuccesseur
|| ''' du support de numéro ''' || theSuccesseur
|| '''.' ;
END IF ;
END IF ;
-------------------------------------------------------------
-- Pas d'erreur : on ajoute le support et on dégage
-------------------------------------------------------------
RETURN NEW ;
END ;
$le_trigger$
LANGUAGE plpgsql ;
CREATE TRIGGER SUPPORT_DISTANCE_COHERENCE_TR BEFORE INSERT ON SUPPORT
FOR EACH ROW EXECUTE PROCEDURE SUPPORT_DISTANCE_COHERENCE_INSERT_FN() ;
Un début de jeu d’essai
INSERT INTO COMMUNE (CommuneInsee, CommuneNom) VALUES (56061, 'La Gacilly') ;
INSERT INTO COMMUNE (CommuneInsee, CommuneNom) VALUES (35328, 'Sixt-sur-Aff') ;
INSERT INTO COMMUNE (CommuneInsee, CommuneNom) VALUES (35168, 'Maure-de-Bretagne') ;
-- SELECT *, '' AS 'COMMUNE' FROM COMMUNE ;
INSERT INTO LIGNE (LigneNom, Tension) VALUES ('Ligne 01', 1000) ;
INSERT INTO LIGNE (LigneNom, Tension) VALUES ('Ligne 02', 2000) ;
INSERT INTO LIGNE (LigneNom, Tension) VALUES ('Ligne 03', 3000) ;
INSERT INTO LIGNE (LigneNom, Tension) VALUES ('Ligne 04', 4000) ;
-- SELECT *, '' AS 'LIGNE' FROM LIGNE ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (10, 0 , 1, 1) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (50, 50 , 2, 1) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (60, 68, 3, 1) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (80, 102, 3, 1) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (190, 150, 3, 1) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (678, 0, 3, 4) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (670, 99, 3, 4) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (640, 210, 3, 4) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (600, 350, 3, 4) ;
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (87, 130, 3, 1) ; -- injection correcte (asc)
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (15, 25, 3, 1) ; -- injection correcte (asc)
INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (620, 230, 3, 4) ; -- injection correcte (desc)
--INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (70, 65, 3, 1) ; -- injection erreur distance (asc)
--INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (610, 360, 3, 4) ; -- injection erreur distance (desc)
--INSERT INTO SUPPORT (SupportNo, DistanceCumul, CommuneId, LigneId) VALUES (140, 300, 3, 1) ; -- injection erreur distance (asc)
SELECT LigneId, SupportNo, DistanceCumul, SensParcours FROM SUPPORT ORDER BY LigneId, SupportNo ;
Au résultat :
Partager