2 votos

Error de commit al dividir varios polígonos con el atributo "tipo array" (PostGIS / QGIS)

Tengo una simple tabla PostGIS :

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)
)

El campo 'liste' es de tipo array ;

Cuando divido los polígonos uno a uno con la herramienta de división de QGIS, no hay ningún problema.

Cuando divido varios polígonos que tienen todos al menos 2 dimensiones en el tipo de array "liste", no hay ningún problema ...

PERO cuando divido varios polígonos que tienen menos de 2 dimensiones en el array tipo "liste" (0 o 1) tengo un error como este :

No se han podido confirmar los cambios en la capa elem_p

Errores: ÉXITO: Se han cambiado 2 geometrías. ERROR: 2 característica(s) no añadido. Errores del proveedor: Error de PostGIS al añadir características: ERROR: matriz literal mal formada: "abcd". DETALLE: El valor de la matriz debe comenzar con "{" o con el información sobre las dimensiones.

(traducción cruda del francés : "construir erróneamente el array : "abcd" ; DETALLE : el valor del array debe comenzar con "{" o con información sobre la dimensión)

enter image description here

EDITAR : El nuevo guión completo :

/* 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)))

1voto

mathieu Puntos 53

Recogiendo los comentarios, y refiriéndome a su edición:

Para solucionar el aparente error con un proxy Ver lo harás mantener una columna de cadenas en lugar de la matriz original, o surgirán los mismos problemas.

Utilice

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()
;

en su lugar. El Ver contendrá una cadena, concatenada a partir de la matriz (cambie el concatenador si es necesario, pero recuerde cambiar el regexp en la función de activación).

No hace falta decir que entonces hay que trabajar con una sola cadena en QGIS en lugar de una matriz.

Obsérvese que en este caso particular (geometrías de división), la cuestión se plantea para el INSERT sólo la operación. Mientras no cambie el liste valores, no se necesita un UPDATE manipulador.


Este podría se manejan con un CAST pero como requiere coaccionar un literal de cadena inicial no decorado (como UNKNOWN pseudotipo) en VARCHAR dentro de una función, requeriría una C las funciones del lenguaje de alto nivel no aceptan todavía los pseudotipos. Dado que la adición de castings también puede tener un montón de consecuencias imprevistas, no voy a añadir eso aquí.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X