1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- PostGIS - Spatial Types for PostgreSQL
-- http://postgis.net
--
-- Copyright (C) 2015 Sandro Santilli <strk@kbt.io>
--
-- This is free software; you can redistribute and/or modify it under
-- the terms of the GNU General Public Licence. See the COPYING file.
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/* #define POSTGIS_TOPOLOGY_DEBUG 1 */
-- {
-- Add an element to a TopoGeometry definition
--
-- }{
CREATE OR REPLACE FUNCTION topology.TopoGeom_addElement(tg topology.TopoGeometry, el topology.TopoElement)
RETURNS topology.TopoGeometry
AS
$$
DECLARE
toponame TEXT;
sql TEXT;
BEGIN
-- Get topology name
BEGIN
SELECT name
FROM topology.topology
INTO STRICT toponame WHERE id = topology_id(tg);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE EXCEPTION 'No topology with name "%" in topology.topology',
atopology;
END;
-- Insert new element
sql := format('INSERT INTO %s.relation'
'(topogeo_id,layer_id,element_id,element_type)'
' VALUES($1,$2,$3,$4)', quote_ident(toponame));
BEGIN
EXECUTE sql USING id(tg), layer_id(tg), el[1], el[2];
EXCEPTION
WHEN unique_violation THEN
-- already present, let go
WHEN OTHERS THEN
RAISE EXCEPTION 'Got % (%)', SQLERRM, SQLSTATE;
END;
RETURN tg;
END
$$
LANGUAGE 'plpgsql' VOLATILE STRICT;
-- }
-- {
-- Remove an element from a TopoGeometry definition
--
-- }{
CREATE OR REPLACE FUNCTION topology.TopoGeom_remElement(tg topology.TopoGeometry, el topology.TopoElement)
RETURNS topology.TopoGeometry
AS
$$
DECLARE
toponame TEXT;
sql TEXT;
BEGIN
-- Get topology name
BEGIN
SELECT name
FROM topology.topology
INTO STRICT toponame WHERE id = topology_id(tg);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE EXCEPTION 'No topology with name "%" in topology.topology',
atopology;
END;
-- Delete the element
sql := format('DELETE FROM %s.relation WHERE '
'topogeo_id = $1 AND layer_id = $2 AND '
'element_id = $3 AND element_type = $4',
quote_ident(toponame));
EXECUTE sql USING id(tg), layer_id(tg), el[1], el[2];
RETURN tg;
END
$$
LANGUAGE 'plpgsql' VOLATILE STRICT;
-- }
-- {
-- Add the component of a TopoGeometry to the definition of
-- another TopoGeometry.
--
-- The two TopoGeometry objects need to be defined on the *same*
-- topology and need to be compatible (both simple or built over
-- the same child layer, and the target TopoGeometry needs to allow
-- for holding components of the type found in the source TopoGeometry)
--
-- }{
CREATE OR REPLACE FUNCTION topology.TopoGeom_addTopoGeom(tgt topology.TopoGeometry, src topology.TopoGeometry)
RETURNS topology.TopoGeometry
AS
$BODY$
DECLARE
sql TEXT;
topo topology.topology;
srcElementTypes int[];
srcLayer topology.layer;
tgtLayer topology.layer;
maxElemType int;
BEGIN
-- Get topology information
topo := topology.FindTopology(topology_id(src));
#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Source TopoGeometry is "%", its topology_id is "%"', src, topo.id;
#endif
IF topology_id(src) != topology_id(tgt) THEN
RAISE EXCEPTION 'Source and target TopoGeometry objects need be defined on the same topology';
END IF;
#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Target TopoGeometry is "%"', tgt;
#endif
SELECT * FROM topology.layer
WHERE topology_id = topo.id
AND layer_id = layer_id(src)
INTO srcLayer;
SELECT * FROM topology.layer
WHERE topology_id = topo.id
AND layer_id = layer_id(tgt)
INTO tgtLayer;
-- Check simple/hierarchical compatibility
IF srcLayer.child_id IS NULL THEN
IF srcLayer.child_id IS NOT NULL THEN
RAISE EXCEPTION 'Cannot add components of hierarchical TopoGeometry to a non-hierarchical TopoGeometry';
END IF;
ELSIF tgtLayer.child_id IS NULL THEN
RAISE EXCEPTION 'Cannot add components of non-hierarchical TopoGeometry to a hierarchical TopoGeometry';
ELSIF tgtLayer.child_id != srcLayer.childId THEN
RAISE EXCEPTION 'Cannot add components of hierarchical TopoGeometry to a hierarchical TopoGeometry based on different layer';
END IF;
-- Add every element of the source TopoGeometry to
-- the definition of the target TopoGeometry
sql := format($$
WITH inserted AS (
INSERT INTO %1$I.relation(
topogeo_id,
layer_id,
element_id,
element_type
)
SELECT %2$s, %3$s, element_id, element_type
FROM %1$I.relation
WHERE topogeo_id = %4$L
AND layer_id = %5$L
EXCEPT
SELECT %2$s, %3$s, element_id, element_type
FROM %1$I.relation
WHERE topogeo_id = %2$L
AND layer_id = %3$L
RETURNING element_type
)
SELECT array_agg(DISTINCT element_type) FROM inserted
$$,
topo.name, -- %1
id(tgt), -- %2
layer_id(tgt), -- %3
id(src), -- %4
layer_id(src) -- %5
);
RAISE DEBUG 'SQL: %', sql;
EXECUTE sql INTO srcElementTypes;
-- TODO: Check layer's feature_type compatibility ?
-- or let the relationTrigger take care of it ?
-- IF tgtLayer.feature_type != 4 THEN -- 'mixed' typed target can accept anything
-- IF srcLayer.feature_type != tgtLayer.feature_type THEN
-- END IF;
-- END IF;
RAISE DEBUG 'Target type: %', type(tgt);
RAISE DEBUG 'Detected source element types: %', srcElementTypes;
-- Check if target TopoGeometry type needs be changed
IF type(tgt) != 4 -- collection TopoGeometry accept anything
THEN
IF array_upper(srcElementTypes, 1) > 1
OR srcElementTypes[1] != tgt.type
THEN
-- source is mixed-typed or typed differently from
-- target, so we turn target type to collection
RAISE DEBUG 'Changing target element type to collection';
tgt.type = 4;
END IF;
END IF;
RETURN tgt;
END
$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT;
-- }
|