[PostGIS] #5983: Data corruption in topology.topoelement and topology.topogeometry after upgrade to 3.6.0

PostGIS trac at osgeo.org
Wed Oct 29 19:21:08 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):

 I still need to test this some more but this is a WIP of a function.

 I'm going to focus on creating upgrade tests for damaged topogeoms and
 then try to fix with this function and will write a companion function to
 check damaged topogeometries.


 {{{
 CREATE OR REPLACE FUNCTION topology.fix_topogeometry_column(topo_schema
 name, topo_table name, topo_column name) RETURNS text AS
 $$
 DECLARE var_sql text; var_row_count bigint; result text;
 BEGIN
         -- if topogeometry is bigint, then fix damaged integer, need to
 upgrade to bigint
         IF EXISTS ( SELECT 1
                 FROM  pg_catalog.pg_type
                         join pg_class on pg_class.oid = pg_type.typrelid
                         join pg_catalog.pg_attribute AS pga  on
 pga.attrelid = pg_class.oid
                         join pg_type as pg_attr_type on pg_attr_type.oid =
 pga.atttypid
 WHERE pg_type.typname::regtype::text = 'topogeometry' AND pga.attname =
 'id'
                         AND
                 pg_type.typnamespace::regnamespace::text = 'topology' AND
 pga.atttypid::regtype::text = 'bigint' ) THEN
          var_sql =  format('UPDATE %1$I.%2$I
                 SET
            %3$I = (
              (%3$I).topology_id,
             (%3$I).layer_id,
              (%3$I).id & 0xFFFFFFFF,
              (%3$I).id >> 32
            )::topogeometry
          WHERE (  (%3$I).id & 0xFFFFFFFF ) <> (%3$I).id OR  (  (%3$I).id
 >> 32 ) = (%3$I).type  ', topo_schema, topo_table, topo_column);

          EXECUTE var_sql;
          GET DIAGNOSTICS var_row_count = ROW_COUNT;
          result = format('%s rows updated for %s.%s.%s column to bigint id
 type', var_row_count, topo_schema, topo_table, topo_column);
   ELSE --we are coming from bigint and going back to integer
         var_sql =  format('UPDATE %1$I.%2$I
                 SET
            %3$I = (
              (%3$I).topology_id,
             (%3$I).layer_id,
              (%3$I).id,
              l.feature_type
            )::topogeometry
            FROM topology.layer AS l
          WHERE  l.topology_id = (%3$I).topology_id AND l.layer_id =
 (%3$I).layer_id AND (%3$I).type <> l.feature_type  ', topo_schema,
 topo_table, topo_column);
          EXECUTE var_sql;
          GET DIAGNOSTICS var_row_count = ROW_COUNT;
          result = format('%s rows updated for %s.%s.%s column back to
 integer id type', var_row_count, topo_schema, topo_table, topo_column);
   END IF;
   RETURN result;
 END
 $$ language plpgsql;
 }}}


 Use case, we would run across all layers in the database and it will fix
 broken rows


 {{{
 SELECT topology.fix_topogeometry_column(schema_name, table_name,
 feature_column)
 FROM topology.layer;
 }}}
-- 
Ticket URL: <https://trac.osgeo.org/postgis/ticket/5983#comment:24>
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