Skip to content

Commit 9d72526

Browse files
committed
WIP: still needs work
- Fix for topogeometry corruption - Add tests - Add documentation for new function
1 parent 26639a2 commit 9d72526

6 files changed

Lines changed: 125 additions & 10 deletions

File tree

doc/extras_topology.xml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,57 @@ Rename a topology from <varname>topo_stage</varname> to <varname>topo_prod</varn
553553
</refsection>
554554
</refentry>
555555

556+
<refentry xml:id="FixCorruptTopoGeometryColumn">
557+
<refnamediv>
558+
<refname>FixCorruptTopoGeometryColumn</refname>
559+
<refpurpose>Fixes topogeometry corruption caused by upgrade to postgis_topology 3.6.0 and higher</refpurpose>
560+
</refnamediv>
561+
<refsynopsisdiv>
562+
<funcsynopsis>
563+
<funcprototype>
564+
<funcdef>text <function>FixCorruptTopoGeometryColumn</function></funcdef>
565+
<paramdef><type>name </type>
566+
<parameter>layerSchema</parameter></paramdef>
567+
<paramdef><type>name </type>
568+
<parameter>layerTable</parameter></paramdef>
569+
<paramdef><type>name </type>
570+
<parameter>layerColumn </parameter></paramdef>
571+
</funcprototype>
572+
</funcsynopsis>
573+
</refsynopsisdiv>
574+
575+
<refsection>
576+
<title>Description</title>
577+
578+
<para>
579+
When upgrading from PostGIS topology &lt;3.6.0 to version &gt;3.6.0+, the topogeometry column definition was changed.
580+
This caused corruption in topogeometries created before the upgrade. This function fixes this corruption in affected tables.
581+
</para>
582+
583+
<!-- use this format if new function -->
584+
<para role="availability" conformance="3.6.1">Availability: 3.6.1</para>
585+
586+
</refsection>
587+
588+
<refsection>
589+
<title>Examples</title>
590+
<para>Fix all topology columns</para>
591+
<programlisting>
592+
SELECT topology.FixCorruptTopoGeometryColumn(schema_name, table_name, feature_column)
593+
FROM topology.layer;
594+
</programlisting>
595+
</refsection>
596+
597+
<!-- Optionally add a "See Also" section -->
598+
<refsection>
599+
<title>See Also</title>
600+
601+
<para>
602+
<xref linkend="UpgradeTopology"/>
603+
</para>
604+
</refsection>
605+
</refentry>
606+
556607
<refentry xml:id="Populate_Topology_Layer">
557608
<refnamediv>
558609
<refname>Populate_Topology_Layer</refname>

topology/sql/manage/FixCorruptTopoGeometryColumn.sql.in

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,50 @@
1818
CREATE OR REPLACE FUNCTION topology.FixCorruptTopoGeometryColumn(layerSchema name, layerTable name, layerColumn name)
1919
RETURNS text AS
2020
$$
21-
DECLARE var_sql text; var_row_count bigint; result text;
21+
DECLARE var_sql text; var_row_count bigint; result text; var_create_index_sql text; var_drop_index_sql text;
2222
BEGIN
23+
result = '';
2324
-- if topogeometry is bigint, then fix damaged integer, need to upgrade to bigint
2425
IF EXISTS ( SELECT 1
2526
FROM pg_catalog.pg_type AS pg_type
2627
JOIN pg_catalog.pg_class AS pg_class ON pg_class.oid = pg_type.typrelid
2728
JOIN pg_catalog.pg_attribute AS pga ON pga.attrelid = pg_class.oid
2829
JOIN pg_catalog.pg_type AS pg_attr_type on pg_attr_type.oid = pga.atttypid
29-
WHERE pg_type.typname::regtype::text = 'topogeometry' AND pga.attname = 'id'
30+
WHERE pg_type.typname = 'topogeometry' AND pga.attname = 'id'
3031
AND
3132
pg_type.typnamespace::regnamespace::text = 'topology' AND pga.atttypid::regtype::text = 'bigint' ) THEN
33+
34+
-- generate index scripts to create and drop indexes that are based on the column
35+
IF EXISTS( SELECT 1 FROM pg_indexes WHERE schemaname = layerSchema AND tablename = layerTable AND indexdef LIKE '%(' || layerColumn || ')%' ) THEN
36+
SELECT string_agg(indexdef, ';'), string_agg('DROP INDEX ' || quote_ident(schemaname) || '.' || quote_ident(indexname), ';') INTO var_create_index_sql, var_drop_index_sql
37+
FROM pg_indexes
38+
WHERE schemaname = layerSchema
39+
AND tablename = layerTable AND indexdef LIKE ('%(' || layerColumn || ')%');
40+
END IF;
41+
42+
IF var_drop_index_sql > '' THEN
43+
EXECUTE var_drop_index_sql;
44+
END IF;
45+
46+
-- correct any corrupt topogeometries and fix
3247
var_sql = format('UPDATE %1$I.%2$I
3348
SET
3449
%3$I = (
3550
(%3$I).topology_id,
3651
(%3$I).layer_id,
37-
(%3$I).id & 0xFFFFFFFF,
38-
(%3$I).id >> 32
52+
((%3$I).id & 0xFFFFFFFF)::bigint,
53+
((%3$I).id >> 32)::integer
3954
)::topology.topogeometry
40-
WHERE ( (%3$I).id & 0xFFFFFFFF ) <> (%3$I).id OR ( (%3$I).id >> 32 ) = (%3$I).type ', layerSchema, layerTable, layerColumn);
55+
WHERE ( (%3$I).id & 0xFFFFFFFF )::bigint <> (%3$I).id OR ( (%3$I).id >> 32 )::integer = (%3$I).type ', layerSchema, layerTable, layerColumn);
4156

4257
EXECUTE var_sql;
4358
GET DIAGNOSTICS var_row_count = ROW_COUNT;
44-
result = format('%s rows updated for %s.%s.%s column to bigint id type', var_row_count, layerSchema, layerTable, layerColumn);
59+
60+
IF var_create_index_sql > '' THEN
61+
EXECUTE var_create_index_sql;
62+
result = result || E'\n' || 'Recreating indexes';
63+
END IF;
64+
result = result || E'\n' || format('%s rows updated for %s.%s.%s column to bigint id type', var_row_count, layerSchema, layerTable, layerColumn);
4565
ELSE --we are coming from bigint and going back to integer
4666
var_sql = format('UPDATE %1$I.%2$I
4767
SET
@@ -55,7 +75,7 @@ WHERE pg_type.typname::regtype::text = 'topogeometry' AND pga.attname = 'id'
5575
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);
5676
EXECUTE var_sql;
5777
GET DIAGNOSTICS var_row_count = ROW_COUNT;
58-
result = format('%s rows updated for %s.%s.%s column back to integer id type', var_row_count, topo_schema, topo_table, topo_column);
78+
result = result || format('%s rows updated for %s.%s.%s column back to integer id type', var_row_count, topo_schema, topo_table, topo_column);
5979
END IF;
6080
RETURN result;
6181
END
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set client_min_messages to WARNING;
2+
3+
\i :top_builddir/topology/test/load_topology-4326.sql
4+
\i ../load_features.sql
5+
\i ../more_features.sql
6+
\i ../hierarchy.sql
7+
SELECT * FROM topology.layer;
8+
SELECT topology.FixCorruptTopoGeometryColumn(schema_name, table_name, feature_column)
9+
FROM topology.layer
10+
WHERE schema_name > '' AND table_name > '' AND feature_column > '';
11+
12+
SELECT topology.DropTopology('city_data');
13+
DROP SCHEMA features CASCADE;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
162|1|features|land_parcels|feature|3|0|
2+
162|2|features|traffic_signs|feature|1|0|
3+
162|3|features|city_streets|feature|2|0|
4+
162|4|features|big_parcels|feature|3|1|1
5+
162|5|features|big_streets|feature|2|1|3
6+
162|6|features|big_signs|feature|1|1|2
7+
0 rows updated for features.land_parcels.feature column to bigint id type
8+
0 rows updated for features.traffic_signs.feature column to bigint id type
9+
0 rows updated for features.city_streets.feature column to bigint id type
10+
0 rows updated for features.big_parcels.feature column to bigint id type
11+
0 rows updated for features.big_streets.feature column to bigint id type
12+
0 rows updated for features.big_signs.feature column to bigint id type
13+
Topology 'city_data' dropped

topology/test/regress/hooks/hook-after-upgrade-topology.sql

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1+
SELECT * FROM topology.layer;
2+
\d upgrade_test.feature
3+
-- https://trac.osgeo.org/postgis/ticket/5983
4+
SELECT topology.FixCorruptTopoGeometryColumn(schema_name, table_name, feature_column)
5+
FROM topology.layer;
6+
7+
\d upgrade_test.feature
8+
19
-- See https://trac.osgeo.org/postgis/ticket/5102
210
SELECT topology.CopyTopology('upgrade_test', 'upgrade_test_copy');
11+
INSERT INTO upgrade_test.domain_test values (
12+
'{1,2}'::topology.topoelement,
13+
'{{2,3}}'::topology.topoelementarray
14+
);
15+
16+
SELECT * FROM topology.layer;
317

4-
-- check if corruption
5-
select geometrytype(tg) from upgrade_test.feature limit 2;
18+
INSERT INTO upgrade_test.domain_test values (
19+
'{1,2}'::topology.topoelement,
20+
'{{2,3}}'::topology.topoelementarray
21+
);
622

723
SELECT topology.DropTopology('upgrade_test');
824
SELECT topology.DropTopology('upgrade_test_copy');

topology/test/tests.mk

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,6 @@ TESTS += \
9797
$(top_srcdir)/topology/test/regress/validatetopologyrelation_large.sql \
9898
$(top_srcdir)/topology/test/regress/validatetopology.sql \
9999
$(top_srcdir)/topology/test/regress/validatetopology_large.sql \
100-
$(top_srcdir)/topology/test/regress/verifylargeids.sql
100+
$(top_srcdir)/topology/test/regress/verifylargeids.sql \
101+
$(top_srcdir)/topology/test/regress/fix_topogeometry_columns.sql
102+

0 commit comments

Comments
 (0)