Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oubliĂ© ?

#1 Thu 14 December 2023 13:11

idjepacreutz
Juste Inscrit !
Date d'inscription: 14 Dec 2023
Messages: 2

Trigger PostgreSQL/PostGIS : découper des lignes sur des polygones

Bonjour,

J'essaie de créer un trigger dans notre base de données PostgreSQL/PostGIS afin de découper les géométries linéaires d'une couche segment sur les polygones d'une couche communes à chaque mise à jour du champ geom (dont sur les opérations INSERT et UPDATE), et de mettre à jour des champs qui contiennent les codes INSEE des différents niveaux de collectivité (tous déjà stockés commune par commune).

Le fonctionnement voulu est celui-ci :

- INSERT : la nouvelle entitĂ© doit ĂȘtre dĂ©coupĂ©e sur les limites de la couche communes, et chaque ligne rĂ©sultant de cette opĂ©ration doit avoir les attributs du polygone dans lequel elle est contenue
- UPDATE : l'entitĂ© prĂ©existant doit continuer d'exister (conservation de l'id et de la date de crĂ©ation de l'entitĂ©), mais avec sa nouvelle gĂ©omĂ©trie (dĂ©coupĂ©e sur les communes), et de nouveaux attributs si nĂ©cessaire. Les nouvelles entitĂ©s issues du dĂ©coupage doivent ĂȘtre insĂ©rĂ©es dans la mĂȘme table.

J'ai du mal Ă  obtenir le bon retour depuis la fonction PL/pgSQL, mon code ci-dessous met bien Ă  jour l'entitĂ© existante (attributs et gĂ©omĂ©trie), mais les entitĂ©s qui sont supposĂ©es ĂȘtre insĂ©rĂ©es ne le sont pas. J'ai essayĂ© de nombreuses combinaisons de RETURN diffĂ©rentes, sans succĂšs. Quelqu'un aurait un conseil ?

Code:

CREATE OR REPLACE FUNCTION split_segments_on_communes_and_update_collectivities_codes() 
RETURNS TRIGGER AS
$BODY$
DECLARE
rec RECORD;
BEGIN
    FOR rec IN
        SELECT c.insee_com AS insee_com,
               '0' || c.insee_dep AS insee_dep,
               c.insee_reg AS insee_reg,
               c.code_epci AS code_epci,
               (ST_Dump(ST_Intersection(NEW.geom, c.geom))).geom AS geom,
               (ST_Dump(ST_Intersection(NEW.geom, c.geom))).path[0] AS "path",
               NEW.id_statut,
               NEW.propriete,
               NEW.author,
               NEW.create_date
          FROM donnees_externes.commune c
          WHERE ST_Intersects(NEW.geom, c.geom)
    LOOP
        IF rec."path" = 1 OR rec."path" IS NULL THEN
            NEW.geom = rec.geom;
            NEW.code_reg = rec.insee_reg;
            NEW.code_dep = rec.insee_dep;
            NEW.code_epci = rec.code_epci;
            NEW.code_commune = rec.insee_com;
        ELSE
            INSERT INTO reference.segment (geom,
                                           id_statut,
                                           propriete,
                                           code_epci,
                                           code_dep,
                                           code_reg,
                                           author,
                                           create_date,
                                           code_commune)
            VALUES (
                   rec.geom,
                   NEW.id_statut,
                   NEW.propriete,
                   rec.code_epci,
                   rec.insee_dep,
                   rec.insee_reg,
                   NEW.author,
                   NEW.create_date,
                   rec.insee_com);
        END IF;
    END LOOP;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;

CREATE OR REPLACE TRIGGER split_segments_on_communes_and_update_collectivities_codes
 BEFORE INSERT
    OR UPDATE OF geom
    ON reference.segment
 FOR EACH ROW
 WHEN (pg_trigger_depth() < 1)
 EXECUTE PROCEDURE split_segments_on_communes_and_update_collectivities_codes();

Hors ligne

 

#2 Tue 19 December 2023 17:33

idjepacreutz
Juste Inscrit !
Date d'inscription: 14 Dec 2023
Messages: 2

Re: Trigger PostgreSQL/PostGIS : découper des lignes sur des polygones

Le problÚme était dans l'utilisation de `path` dans cette ligne : `(ST_Dump(ST_Intersection(NEW.geom, c.geom))).path[0] AS "path"`.

VoilĂ  la bonne maniĂšre de faire :

Code:

WITH parts AS (
            SELECT c.insee_com AS insee_com,
                   '0' || c.insee_dep AS insee_dep,
                   c.insee_reg AS insee_reg,
                   c.code_epci AS code_epci,
                   (ST_Dump(ST_Intersection(NEW.geom, c.geom))).geom AS geom,
                   NEW.id_statut,
                   NEW.propriete,
                   NEW.author,
                   NEW.create_date
              FROM donnees_externes.commune c
             WHERE ST_Intersects(NEW.geom, c.geom)
        )
        SELECT *,
               ROW_NUMBER() OVER () AS "path"
          FROM parts

Et la fonction complĂšte :

Code:

CREATE OR REPLACE FUNCTION reference.split_segments_on_communes_and_update_collectivities_codes()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
DECLARE
rec RECORD;
newgeom geometry;
BEGIN
    FOR rec IN
        WITH parts AS (
            SELECT c.insee_com AS insee_com,
                   '0' || c.insee_dep,
                   c.insee_reg AS insee_reg,
                   c.code_epci AS code_epci,
                   (ST_Dump(ST_Intersection(NEW.geom, c.geom))).geom AS geom
              FROM donnees_externes.commune c
             WHERE ST_Intersects(NEW.geom, c.geom)
        )
        SELECT *,
               ROW_NUMBER() OVER () AS "path"
          FROM parts
    LOOP 
        IF ST_GeometryType(rec.geom) != 'ST_Point' THEN
           IF rec."path" = 1 THEN
              NEW.geom := rec.geom;
              NEW.code_reg := rec.insee_reg;
              NEW.code_dep := rec.insee_dep;
              NEW.code_epci := rec.code_epci;
              NEW.code_commune := rec.insee_com;
           ELSE
              INSERT INTO reference.segment (geom,
                                             id_statut,
                                             propriete,
                                             code_epci,
                                             code_dep,
                                             code_reg,
                                             author,
                                             create_date,
                                             code_commune)
              VALUES (
                     rec.geom,
                     NEW.id_statut,
                     NEW.propriete,
                     rec.code_epci,
                     rec.insee_dep,
                     rec.insee_reg,
                     NEW.author,
                     NEW.create_date,
                     rec.insee_com);
           END IF;
        END IF;
    END LOOP;
RETURN NEW;
END;
$function$
;

Dernière modification par idjepacreutz (Tue 19 December 2023 17:33)

Hors ligne

 

#3 Tue 19 December 2023 19:32

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1566

Re: Trigger PostgreSQL/PostGIS : découper des lignes sur des polygones

Bonsoir,

Attention, en ne faisant pas de "order by" dans la CTE "parts", la valeur de path peut etre différente suivant les appels à cette fonction.

Nicolas

Hors ligne

 

Pied de page des forums

Copyright Association GeoRezo