I have a simple PostGIS table :
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)
)
The 'liste' field is array-type ;
When I split polygons one-by-one with the QGIS splitting tool, there is no problem.
When I split several polygons that all have at least 2 dimension in the array type "liste", there is no problem ...
BUT when I split several polygons that have less than 2 dimensions in the array type "liste" (0 or 1) I have an error like this :
Could not commit changes to layer elem_p
Errors: SUCCESS: 2 geometries were changed. ERROR: 2 feature(s) not added. Provider errors: PostGIS error while adding features: ERREUR: tableau litéral mal formé : « abcd » DETAIL: La valeur du tableau doit commencer avec « { » ou avec l'information de la dimension.
(raw translation from french : "wrongly build array : "abcd" ; DETAIL : array value must start with "{" or with information about dimension)
EDIT : The whole new script :
/* 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)))
BEFORE
trigger, or aRULE
on the table itself would be enough to coerce values into the array prior to upserting. However, the most appropriate solution would be to normalize that table into a geometry table and a related attribute table, since you effectively duplicate theliste
values for each split geometry.