]> granicus.if.org Git - postgis/commitdiff
Ticket #856: topology.CopyTopology(text,text) implementation, test and documentation
authorSandro Santilli <strk@keybit.net>
Wed, 9 Mar 2011 19:18:45 +0000 (19:18 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 9 Mar 2011 19:18:45 +0000 (19:18 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@6888 b70326c6-7e19-0410-871a-916f4a2858ee

doc/extras_topology.xml
topology/Makefile.in
topology/sql/manage/CopyTopology.sql [new file with mode: 0644]
topology/test/Makefile
topology/test/regress/copytopology.sql [new file with mode: 0644]
topology/test/regress/copytopology_expected [new file with mode: 0644]
topology/topology.sql.in.c

index ac39a866ac6ff49ec84953fb01e5a37fcd9279d4..eeaecf27d60a6b3cfbbc25235467776952a905b0 100644 (file)
@@ -393,6 +393,54 @@ topoid
                                <para></para>
                        </refsection>
                </refentry>
+               <refentry id="CopyTopology">
+                       <refnamediv>
+                               <refname>CopyTopology</refname>
+                               <refpurpose>Makes a copy of a topology structure (nodes, edges, faces, layers and TopoGeometries).</refpurpose>
+                       </refnamediv>
+               
+                       <refsynopsisdiv>
+                               <funcsynopsis>
+                                       <funcprototype>
+                                               <funcdef>integer <function>CopyTopology</function></funcdef>
+                                               <paramdef><type>varchar </type> <parameter>existing_topology_name</parameter></paramdef>
+                                               <paramdef><type>varchar </type> <parameter>new_name</parameter></paramdef>
+                                       </funcprototype>
+                               </funcsynopsis>
+                       </refsynopsisdiv>
+               
+                       <refsection>
+                <title>Description</title>
+            
+                <para>
+Creates a new topology with name <varname>new_topology_name</varname> and SRID and precision taken from <varname>existing_topology_name</varname>, copies all nodes, edges and faces in there, copies layers and their TopoGeometries too.
+               </para>
+                
+                <note><para>
+The new rows in topology.layer will contain synthetized values for schema_name, table_name and feature_column. This is because the TopoGeometry will only exist as a definition but won't be available in any user-level table yet.
+               </para></note>
+        
+                <!-- use this format if new function -->
+                <para>Availability: 2.0.0</para>
+                       </refsection>
+               
+               
+                       <refsection>
+                               <title>Examples</title>
+                               <para>
+This example makes a backup of a topology called ma_topo 
+                               </para>
+                               <programlisting>SELECT topology.CopyTopology('ma_topo', 'ma_topo_bakup');</programlisting>
+                               
+                       </refsection>
+               
+                       <!-- Optionally add a "See Also" section -->
+                       <refsection>
+                               <title>See Also</title>
+                       
+                               <para><xref linkend="spatial_ref_sys"/>, <xref linkend="CreateTopology" /></para>
+                       </refsection>
+               </refentry>
                <refentry id="DropTopoGeometryColumn">
                        <refnamediv>
                                <refname>DropTopoGeometryColumn</refname>
index a0ec01b47c86620791b06df76059edd283e7e7f8..9e19bc3227c2a1a787c2df1e724cc9baded92d62 100644 (file)
@@ -42,7 +42,7 @@ endif
 $(SQL_OBJS): %.in: %.in.c
        $(CPP) -traditional-cpp $< | grep -v '^#' > $@
 
-topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/gml.sql sql/query/getnodebypoint.sql sql/query/getedgebypoint.sql sql/manage/TopologySummary.sql
+topology.sql.in: sql/sqlmm.sql sql/populate.sql sql/gml.sql sql/query/getnodebypoint.sql sql/query/getedgebypoint.sql sql/manage/TopologySummary.sql sql/manage/CopyTopology.sql
 
 check: topology.sql
        $(MAKE) -C test $@
diff --git a/topology/sql/manage/CopyTopology.sql b/topology/sql/manage/CopyTopology.sql
new file mode 100644 (file)
index 0000000..a44ec67
--- /dev/null
@@ -0,0 +1,100 @@
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-- 
+-- PostGIS - Spatial Types for PostgreSQL
+-- http://postgis.refractions.net
+--
+-- Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
+--
+-- This is free software; you can redistribute and/or modify it under
+-- the terms of the GNU General Public Licence. See the COPYING file.
+--
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+--{
+-- CopyTopology(name_source, name_target)
+--
+-- Makes a copy of a topology (primitives + topogeometry collections) .
+-- Returns the new topology id.
+--
+CREATE OR REPLACE FUNCTION topology.CopyTopology(atopology varchar,
+                                                 newtopo varchar)
+RETURNS int
+AS
+$$
+DECLARE
+  rec RECORD;
+  rec2 RECORD;
+  oldtopo_id integer;
+  newtopo_id integer;
+  n int4;
+  ret text;
+BEGIN
+
+  SELECT * FROM topology.topology where name = atopology
+  INTO strict rec;
+  oldtopo_id = rec.id;
+  -- TODO: more gracefully handle unexistent topology
+
+  SELECT topology.CreateTopology(newtopo, rec.SRID, rec.precision)
+  INTO strict newtopo_id;
+
+  -- Copy faces
+  EXECUTE 'INSERT INTO ' || quote_ident(newtopo)
+    || '.face SELECT * FROM ' || quote_ident(atopology)
+    || '.face WHERE face_id != 0';
+  -- Update faces sequence
+  EXECUTE 'SELECT setval(' || quote_literal(
+      quote_ident(newtopo) || '.face_face_id_seq'
+    ) || ', (SELECT last_value FROM ' 
+    || quote_ident(atopology) || '.face_face_id_seq))';
+
+  -- Copy nodes
+  EXECUTE 'INSERT INTO ' || quote_ident(newtopo)
+    || '.node SELECT * FROM ' || quote_ident(atopology)
+    || '.node';
+  -- Update node sequence
+  EXECUTE 'SELECT setval(' || quote_literal(
+      quote_ident(newtopo) || '.node_node_id_seq'
+    ) || ', (SELECT last_value FROM ' 
+    || quote_ident(atopology) || '.node_node_id_seq))';
+
+  -- Copy edges
+  EXECUTE 'INSERT INTO ' || quote_ident(newtopo)
+    || '.edge_data SELECT * FROM ' || quote_ident(atopology)
+    || '.edge_data';
+  -- Update edge sequence
+  EXECUTE 'SELECT setval(' || quote_literal(
+      quote_ident(newtopo) || '.edge_data_edge_id_seq'
+    ) || ', (SELECT last_value FROM ' 
+    || quote_ident(atopology) || '.edge_data_edge_id_seq))';
+
+  -- Copy layers and their TopoGeometry sequences 
+  FOR rec IN SELECT * FROM topology.layer WHERE topology_id = oldtopo_id
+  LOOP
+    INSERT INTO topology.layer (topology_id, layer_id, feature_type,
+      level, child_id, schema_name, table_name, feature_column) 
+      VALUES (newtopo_id, rec.layer_id, rec.feature_type,
+              rec.level, rec.child_id, newtopo,
+              'LAYER' ||  rec.layer_id, '');
+    -- Create layer's TopoGeometry sequences
+    EXECUTE 'SELECT last_value FROM ' 
+      || quote_ident(atopology) || '.topogeo_s_' || rec.layer_id 
+      INTO STRICT n;
+    EXECUTE 'CREATE SEQUENCE ' || quote_ident(newtopo)
+      || '.topogeo_s_' || rec.layer_id;
+    EXECUTE 'SELECT setval(' || quote_literal(
+      quote_ident(newtopo) || '.topogeo_s_' || rec.layer_id
+      ) || ', ' || n || ')';
+  END LOOP;
+
+  -- Copy TopoGeometry definitions
+  EXECUTE 'INSERT INTO ' || quote_ident(newtopo)
+    || '.relation SELECT * FROM ' || quote_ident(atopology)
+    || '.relation';
+
+  RETURN newtopo_id;
+END
+$$
+LANGUAGE 'plpgsql' VOLATILE STRICT;
+
+--} TopologySummary
index 7980de4075f27895c46440abc1a338ce34263f7d..ee384eee18d254363e0a1d50e6e22552a419fac1 100644 (file)
@@ -30,6 +30,7 @@ TESTS = regress/legacy_validate.sql regress/legacy_predicate.sql \
        regress/topoelement.sql \
        regress/topoelementarray_agg.sql \
        regress/droptopology.sql \
+       regress/copytopology.sql \
        regress/createtopogeom.sql \
        regress/gml.sql \
        regress/getnodebypoint.sql \
diff --git a/topology/test/regress/copytopology.sql b/topology/test/regress/copytopology.sql
new file mode 100644 (file)
index 0000000..a914bac
--- /dev/null
@@ -0,0 +1,53 @@
+set client_min_messages to WARNING;
+
+INSERT INTO spatial_ref_sys ( auth_name, auth_srid, srid, proj4text ) VALUES ( 'EPSG', 4326, 4326, '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs' );
+\i load_topology-4326.sql
+\i load_features.sql
+\i more_features.sql
+
+SELECT topology.CopyTopology('city_data', 'CITY_data_UP_down') > 0;
+
+SELECT srid,precision FROM topology.topology WHERE name = 'CITY_data_UP_down';
+
+SELECT 'nodes', count(node_id) FROM "CITY_data_UP_down".node;
+SELECT * FROM "CITY_data_UP_down".node EXCEPT
+SELECT * FROM "city_data".node;
+
+SELECT 'edges', count(edge_id) FROM "CITY_data_UP_down".edge_data;
+SELECT * FROM "CITY_data_UP_down".edge EXCEPT
+SELECT * FROM "city_data".edge;
+
+SELECT 'faces', count(face_id) FROM "CITY_data_UP_down".face;
+SELECT * FROM "CITY_data_UP_down".face EXCEPT
+SELECT * FROM "city_data".face;
+
+SELECT 'relations', count(*) FROM "CITY_data_UP_down".relation;
+SELECT * FROM "CITY_data_UP_down".relation EXCEPT
+SELECT * FROM "city_data".relation;
+
+SELECT 'layers', count(l.*) FROM topology.layer l, topology.topology t
+WHERE l.topology_id = t.id and t.name = 'CITY_data_UP_down';
+SELECT l.layer_id, l.feature_type, l.level FROM topology.layer l,
+topology.topology t where l.topology_id = t.id and t.name = 'CITY_data_UP_down'
+EXCEPT
+SELECT l.layer_id, l.feature_type, l.level FROM topology.layer l,
+topology.topology t where l.topology_id = t.id and t.name = 'city_data';
+
+SELECT l.layer_id, l.schema_name, l.table_name, l.feature_column
+FROM topology.layer l, topology.topology t
+WHERE l.topology_id = t.id and t.name = 'CITY_data_UP_down'
+ORDER BY l.layer_id;
+
+-- Check sequences
+SELECT * from "CITY_data_UP_down".node_node_id_seq;
+SELECT * from "CITY_data_UP_down".edge_data_edge_id_seq;
+SELECT * from "CITY_data_UP_down".face_face_id_seq;
+SELECT * from "CITY_data_UP_down".layer_id_seq;
+SELECT * from "CITY_data_UP_down".topogeo_s_1;
+SELECT * from "CITY_data_UP_down".topogeo_s_2;
+SELECT * from "CITY_data_UP_down".topogeo_s_3;
+
+SELECT topology.DropTopology('CITY_data_UP_down');
+SELECT topology.DropTopology('city_data');
+DROP SCHEMA features CASCADE;
+DELETE FROM spatial_ref_sys where srid = 4326;
diff --git a/topology/test/regress/copytopology_expected b/topology/test/regress/copytopology_expected
new file mode 100644 (file)
index 0000000..afeccd7
--- /dev/null
@@ -0,0 +1,30 @@
+BEGIN
+t
+8
+22
+26
+COMMIT
+BEGIN
+1
+2
+3
+COMMIT
+t
+4326|0
+nodes|22
+edges|24
+faces|10
+relations|39
+layers|3
+1|CITY_data_UP_down|LAYER1|
+2|CITY_data_UP_down|LAYER2|
+3|CITY_data_UP_down|LAYER3|
+node_node_id_seq|22|1|1|9223372036854775807|1|1|0|f|t
+edge_data_edge_id_seq|26|1|1|9223372036854775807|1|1|0|f|t
+face_face_id_seq|8|1|1|9223372036854775807|1|1|0|f|t
+layer_id_seq|1|1|1|9223372036854775807|1|1|1|f|f
+topogeo_s_1|9|1|1|9223372036854775807|1|1|0|f|t
+topogeo_s_2|8|1|1|9223372036854775807|1|1|0|f|t
+topogeo_s_3|8|1|1|9223372036854775807|1|1|0|f|t
+Topology 'CITY_data_UP_down' dropped
+Topology 'city_data' dropped
index 518e346a9ddb27f049f1c3f601aa2612b9a1b037..01c3a2f01116eb1a2f5fc2fd080666cd5fa7d46c 100644 (file)
@@ -1908,6 +1908,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT;
 --} DropTopology
 
 #include "sql/manage/TopologySummary.sql"
+#include "sql/manage/CopyTopology.sql"
 
 --={ ----------------------------------------------------------------
 --  POSTGIS-SPECIFIC topology predicates