Commit-Fehler beim Teilen mehrerer Polygone mit dem Attribut "Array-Typ" (PostGIS / QGIS)

Oct 21 2020

Ich habe eine einfache PostGIS-Tabelle:

CREATE TABLE public.elem_p
(
    gid integer NOT NULL DEFAULT nextval('elem_p_gid_seq'::regclass),
    liste character varying[] COLLATE pg_catalog."default" NOT NULL,
    geom geometry(MultiPolygon,2154),
    CONSTRAINT elem_p_pkey PRIMARY KEY (gid)
)

Das Feld 'liste' ist vom Typ Array.

Wenn ich Polygone mit dem QGIS-Aufteilungswerkzeug einzeln teile, gibt es kein Problem.

Wenn ich mehrere Polygone teile, die alle mindestens zwei Dimensionen im Array-Typ "liste" haben, gibt es kein Problem ...

ABER wenn ich mehrere Polygone mit weniger als 2 Dimensionen im Array-Typ "liste" (0 oder 1) teile, tritt ein Fehler wie der folgende auf:

Änderungen an Layer elem_p konnten nicht festgeschrieben werden

Fehler: ERFOLG: 2 Geometrien wurden geändert. FEHLER: 2 Funktion (en) nicht hinzugefügt. Anbieterfehler: PostGIS-Fehler beim Hinzufügen von Funktionen: ERREUR: Tableau litéral mal formé: «abcd» DETAIL: Das valeur du tableau doit begin avec

(Rohübersetzung aus dem Französischen: "Array falsch erstellen:" abcd "; DETAIL: Array-Wert muss mit" {"oder mit Informationen zur Dimension beginnen)

EDIT: Das ganz neue Skript:

/* TABLE */ 
DROP TABLE IF EXISTS elem_p CASCADE ; CREATE TABLE elem_p (gid serial, liste varchar[], geom geometry(multipolygon, 2154)) ;
INSERT INTO elem_p (gid, liste, geom) 
VALUES (nextval('elem_p_gid_seq'::regclass), '{E-1, E-5}', ST_MULTI(ST_SETSRID(st_geomfromtext('POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))'), 2154)))
   ,(nextval('elem_p_gid_seq'::regclass), '{E-1, E-7}', ST_MULTI(ST_SETSRID(st_geomfromtext('POLYGON((10 10, 6 6, 6 7, 6 8, 7 10 , 9 10, 10 10))'), 2154)))
   ,(nextval('elem_p_gid_seq'::regclass), NULL, ST_MULTI(ST_SETSRID(st_geomfromtext('POLYGON((0 10, -3 10, -3 8, -5 5, 0 4, 0 10))'), 2154))) ;
UPDATE elem_p  SET liste = '{E-30}'  WHERE gid = 2 ; 

/* VIEW  */
CREATE OR REPLACE VIEW v_elem_p AS (SELECT * FROM elem_p) ;

/*  FUNCTION  */
DROP FUNCTION IF EXISTS maj_elem_p() CASCADE ;
CREATE FUNCTION maj_elem_p() RETURNS TRIGGER AS 
$$ BEGIN IF TG_OP = 'INSERT' THEN INSERT INTO elem_p (liste, geom) VALUES(COALESCE((NEW.liste::varchar)::varchar[], '{}'::varchar[]), NEW.geom); RETURN NEW; END IF; IF TG_OP = 'UPDATE' THEN UPDATE elem_p SET (liste, geom) = (COALESCE((NEW.liste::varchar)::varchar[], '{}'::varchar[]), NEW.geom) WHERE gid = NEW.gid; RETURN NEW ; END IF ; END; $$  LANGUAGE PLPGSQL ;

/* TRIGGER  */ 
DROP TRIGGER IF EXISTS tg_maj_elem_p  ON v_elem_p ; CREATE TRIGGER tg_maj_elem_p INSTEAD OF INSERT OR UPDATE ON v_elem_p  FOR EACH ROW   EXECUTE PROCEDURE public.maj_elem_p();

/* TESTS */
UPDATE v_elem_p  SET liste = '{E-99}'  WHERE gid = 2 ; 
INSERT INTO v_elem_p VALUES (DEFAULT, '{E-123, E-54}', ST_MULTI(ST_SETSRID(st_geomfromtext('POLYGON((3 3, 5 3, 5 4,5 5, 2 6, 3 3))'), 2154)))

Antworten

1 geozelot Oct 28 2020 at 19:19

Nehmen Sie die Kommentare auf und beziehen Sie sich auf Ihre Bearbeitung:

Um den offensichtlichen Fehler mit einer Proxy- Ansicht zu umgehen, wird eine Zeichenfolgenspalte anstelle des ursprünglichen Arrays gespeichert, da sonst dieselben Probleme auftreten!

Verwenden

CREATE OR REPLACE VIEW elem_p_v AS
    SELECT  gid,
            ARRAY_TO_STRING(liste, ',') AS liste,
            geom
    FROM    elem_p
;

CREATE OR REPLACE FUNCTION elem_p_v_insert_func()
  RETURNS TRIGGER AS
    $$ BEGIN INSERT INTO elem_p (liste, geom) VALUES (REGEXP_SPLIT_TO_ARRAY(NEW.liste, ','), NEW.geom) ; RETURN NEW; END; $$
  LANGUAGE 'plpgsql'
;

CREATE TRIGGER elem_p_check_array_literal
  INSTEAD OF INSERT ON elem_p_v
  FOR EACH ROW
  EXECUTE PROCEDURE elem_p_v_insert_func()
;

stattdessen. Die Ansicht enthält eine vom Array verkettete Zeichenfolge (ändern Sie den Verketter bei Bedarf, aber denken Sie daran, das Regexp- Muster in der Triggerfunktion entsprechend zu ändern ).

Es ist unnötig zu erwähnen, dass Sie dann mit einer einzelnen Zeichenfolge in QGIS und nicht mit einem Array arbeiten müssen.

Beachten Sie, dass in diesem speziellen Fall (Aufteilen von Geometrien) das Problem nur für den tatsächlichen INSERTBetrieb auftritt. Solange Sie die listeWerte nicht ändern , benötigen Sie keinen UPDATEHandler.


Dies könnte mit einer benutzerdefinierten Funktion behandelt CASTwerden. Da jedoch ein anfängliches nicht dekoriertes Zeichenfolgenliteral (als UNKNOWNPseudotyp) in VARCHAReine Funktion gezwungen werden muss, ist eine C- Konvertierungsfunktion erforderlich . Sprachfunktionen höherer Ebenen akzeptieren noch keine Pseudotypen. Da das Hinzufügen von Casts auch viele unvorhergesehene Konsequenzen haben kann, werde ich das hier nicht hinzufügen.