<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>
$(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 $@
--- /dev/null
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+--
+-- 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
regress/topoelement.sql \
regress/topoelementarray_agg.sql \
regress/droptopology.sql \
+ regress/copytopology.sql \
regress/createtopogeom.sql \
regress/gml.sql \
regress/getnodebypoint.sql \
--- /dev/null
+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;
--- /dev/null
+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
--} DropTopology
#include "sql/manage/TopologySummary.sql"
+#include "sql/manage/CopyTopology.sql"
--={ ----------------------------------------------------------------
-- POSTGIS-SPECIFIC topology predicates