[PostGIS] #5983: Data corruption in topology.topoelement and topology.topogeometry after upgrade to 3.6.0
PostGIS
trac at osgeo.org
Wed Oct 15 19:02:17 PDT 2025
#5983: Data corruption in topology.topoelement and topology.topogeometry after
upgrade to 3.6.0
-----------------------+---------------------------
Reporter: packi | Owner: robe
Type: defect | Status: new
Priority: blocker | Milestone: PostGIS 3.6.1
Component: topology | Version: 3.6.x
Resolution: | Keywords:
-----------------------+---------------------------
Comment (by robe):
Okay I think this would fix the broken topogeometries but probably very
slow
{{{
CREATE EXTENSION postgis_topology VERSION "3.4.2";
CREATE OR REPLACE FUNCTION topology.hex_to_int(hexVal varchar) RETURNS
numeric(1000) AS $$
DECLARE
intVal numeric(1000) := 0;
hexLength integer;
i integer;
hexDigit varchar;
BEGIN
hexLength := length(hexVal);
FOR i IN 1..hexLength
LOOP
hexDigit := substr(hexVal, hexLength - i + 1, 1);
intVal :=
intVal +
CASE
WHEN hexDigit BETWEEN '0' AND '9' THEN CAST(hexDigit AS
numeric(1000))
WHEN upper(hexDigit) BETWEEN 'A' AND 'F' THEN
CAST(ascii(upper(hexDigit)) - 55 AS numeric(1000))
END *
CAST(16 AS numeric(1000)) ^ CAST(i - 1 AS numeric(1000));
END LOOP;
RETURN intVal;
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION topology.fix_topogeometry(param_topo
topogeometry) RETURNS topogeometry AS
$$
BEGIN
IF geometrytype(param_topo) != 'UNEXPECTED' THEN -- it's okay
return unchanged
RETURN param_topo;
ELSE
RETURN (param_topo.topology_id, param_topo.layer_id,
topology.hex_to_int(right(lpad(to_hex(param_topo.id), 16,
'0'),8))::bigint, topology.hex_to_int(left(lpad(to_hex(param_topo.id), 16,
'0'),8))::bigint)::topogeometry;
END IF;
END
$$ language plpgsql;
}}}
I tested with a set of mix of bad and good topogeometries upgrading from
postgis_topology 3.4.2 to 3.6.0
{{{
CREATE EXTENSION postgis_topology VERSION '3.4.2';
DROP SCHEMA IF EXISTS tiger_topo CASCADE;
SELECT topology.CreateTopology('tiger_topo', 4326, 0.00001);
DROP TABLE IF EXISTS topo_states;
CREATE TABLE topo_states (stusps char(2));
SELECT topology.AddTopoGeometryColumn('tiger_topo', 'public',
'topo_states', 'topo', 'POLYGON');
INSERT INTO topo_states(stusps, topo)
SELECT stusps, ToTopoGeom(ST_SetSRID(the_geom,4326), 'tiger_topo', 1)
FROM tiger_link.state WHERE stusps IN('MA','DC','RI','NH', 'NY');
}}}
{{{
-- not broken
SELECT stusps, geometrytype(topo) FROM topo_states;
}}}
{{{
stusps | geometrytype | topo
--------+--------------+-----------
RI | MULTIPOLYGON | (1,1,1,3)
NH | MULTIPOLYGON | (1,1,2,3)
NY | MULTIPOLYGON | (1,1,3,3)
MA | MULTIPOLYGON | (1,1,4,3)
DC | MULTIPOLYGON | (1,1,5,3)
}}}
{{{
ALTER EXTENSION postgis_topology UPDATE TO "3.6.0";
-- all broken
SELECT stusps, geometrytype(topo), topo FROM topo_states;
}}}
{{{
stusps | geometrytype | topo
--------+--------------+----------------------------
RI | UNEXPECTED | (1,1,12884901889,19626)
NH | UNEXPECTED | (1,1,12884901890,16676265)
NY | UNEXPECTED | (1,1,12884901891,16676265)
MA | UNEXPECTED | (1,1,12884901892,16676265)
DC | UNEXPECTED | (1,1,12884901893,16676265)
(5 rows)
}}}
{{{
INSERT INTO topo_states(stusps, topo)
SELECT stusps, ToTopoGeom(ST_SetSRID(the_geom,4326), 'tiger_topo', 1)
FROM tiger_link.state WHERE stusps IN('DE');
-- new one not broken
SELECT stusps, geometrytype(topo), topo FROM topo_states;
}}}
{{{
stusps | geometrytype | topo
--------+--------------+----------------------------
RI | UNEXPECTED | (1,1,12884901889,19626)
NH | UNEXPECTED | (1,1,12884901890,16676265)
NY | UNEXPECTED | (1,1,12884901891,16676265)
MA | UNEXPECTED | (1,1,12884901892,16676265)
DC | UNEXPECTED | (1,1,12884901893,16676265)
DE | MULTIPOLYGON | (1,1,6,3)
(6 rows)
}}}
{{{
UPDATE topo_states SET topo = topology.fix_topogeometry(topo) WHERE
geometrytype(topo) = 'UNEXPECTED';
-- all good
SELECT stusps, geometrytype(topo), topo FROM topo_states;
}}}
{{{
stusps | geometrytype | topo
--------+--------------+-----------
DE | MULTIPOLYGON | (1,1,6,3)
RI | MULTIPOLYGON | (1,1,1,3)
NH | MULTIPOLYGON | (1,1,2,3)
NY | MULTIPOLYGON | (1,1,3,3)
MA | MULTIPOLYGON | (1,1,4,3)
DC | MULTIPOLYGON | (1,1,5,3)
(6 rows)
}}}
--
Ticket URL: <https://trac.osgeo.org/postgis/ticket/5983#comment:17>
PostGIS <http://trac.osgeo.org/postgis/>
The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project.
More information about the postgis-tickets
mailing list