source: trunk/topology/sql/sqlmm.sql @ 6589

Last change on this file since 6589 was 6589, checked in by robe, 6 years ago

#760: replace deprecated function names with new names so all regress tests pass again. This should completely work now.

File size: 35.9 KB
Line 
1-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2--
3-- PostGIS - Spatial Types for PostgreSQL
4-- http://postgis.refractions.net
5--
6-- Copyright (C) 2010 Sandro Santilli <strk@keybit.net>
7-- Copyright (C) 2005 Refractions Research Inc.
8--
9-- This is free software; you can redistribute and/or modify it under
10-- the terms of the GNU General Public Licence. See the COPYING file.
11--
12-- Author: Sandro Santilli <strk@refractions.net>
13-- 
14--
15
16--={ ----------------------------------------------------------------
17--  SQL/MM block
18--
19--  This part contains function in the SQL/MM specification
20--
21---------------------------------------------------------------------
22
23
24--{
25-- Topo-Geo and Topo-Net 3: Routine Details
26-- X.3.5
27--
28--  ST_GetFaceEdges(atopology, aface)
29--
30--
31--
32CREATE OR REPLACE FUNCTION topology.ST_GetFaceEdges(varchar, integer)
33        RETURNS setof topology.GetFaceEdges_ReturnType
34AS
35'
36DECLARE
37        atopology ALIAS FOR $1;
38        aface ALIAS FOR $2;
39        rec RECORD;
40BEGIN
41        --
42        -- Atopology and aface are required
43        --
44        IF atopology IS NULL OR aface IS NULL THEN
45                RAISE EXCEPTION
46                 ''SQL/MM Spatial exception - null argument'';
47        END IF;
48
49        RAISE EXCEPTION
50                 ''ST_GetFaceEdges: not implemented yet'';
51
52
53END
54'
55LANGUAGE 'plpgsql' VOLATILE;
56--} ST_GetFaceEdges
57
58
59--{
60-- Topo-Geo and Topo-Net 3: Routine Details
61-- X.3.16
62--
63--  ST_GetFaceGeometry(atopology, aface)
64--
65CREATE OR REPLACE FUNCTION topology.ST_GetFaceGeometry(varchar, integer)
66        RETURNS GEOMETRY AS
67'
68DECLARE
69        atopology ALIAS FOR $1;
70        aface ALIAS FOR $2;
71        rec RECORD;
72BEGIN
73        --
74        -- Atopology and aface are required
75        --
76        IF atopology IS NULL OR aface IS NULL THEN
77                RAISE EXCEPTION
78                 ''SQL/MM Spatial exception - null argument'';
79        END IF;
80
81        --
82        -- Construct face
83        --
84        FOR rec IN EXECUTE ''SELECT ST_BuildArea(ST_Collect(geom)) FROM ''
85                || quote_ident(atopology)
86                || ''.edge WHERE left_face = '' || aface ||
87                '' OR right_face = '' || aface
88        LOOP
89                RETURN rec.st_buildarea;
90        END LOOP;
91
92
93        --
94        -- No face found
95        --
96        RAISE EXCEPTION
97        ''SQL/MM Spatial exception - non-existent face.'';
98END
99' 
100LANGUAGE 'plpgsql' VOLATILE;
101--} ST_GetFaceGeometry
102
103
104--{
105-- Topo-Geo and Topo-Net 3: Routine Details
106-- X.3.1
107--
108--  ST_AddIsoNode(atopology, aface, apoint)
109--
110CREATE OR REPLACE FUNCTION topology.ST_AddIsoNode(varchar, integer, geometry)
111        RETURNS INTEGER AS
112'
113DECLARE
114        atopology ALIAS FOR $1;
115        aface ALIAS FOR $2;
116        apoint ALIAS FOR $3;
117        rec RECORD;
118        nodeid integer;
119BEGIN
120
121        --
122        -- Atopology and apoint are required
123        --
124        IF atopology IS NULL OR apoint IS NULL THEN
125                RAISE EXCEPTION
126                 ''SQL/MM Spatial exception - null argument'';
127        END IF;
128
129        --
130        -- Apoint must be a point
131        --
132        IF substring(geometrytype(apoint), 1, 5) != ''POINT''
133        THEN
134                RAISE EXCEPTION
135                 ''SQL/MM Spatial exception - invalid point'';
136        END IF;
137
138        --
139        -- Check if a coincident node already exists
140        --
141        -- We use index AND x/y equality
142        --
143        FOR rec IN EXECUTE ''SELECT node_id FROM ''
144                || quote_ident(atopology) || ''.node '' ||
145                ''WHERE geom && '' || quote_literal(apoint::text) || ''::geometry''
146                ||'' AND ST_X(geom) = ST_X(''||quote_literal(apoint::text)||''::geometry)''
147                ||'' AND ST_Y(geom) = ST_Y(''||quote_literal(apoint::text)||''::geometry)''
148        LOOP
149                RAISE EXCEPTION
150                 ''SQL/MM Spatial exception - coincident node'';
151        END LOOP;
152
153        --
154        -- Check if any edge crosses (intersects) this node
155        -- I used _intersects_ here to include boundaries (endpoints)
156        --
157        FOR rec IN EXECUTE ''SELECT edge_id FROM ''
158                || quote_ident(atopology) || ''.edge ''
159                || ''WHERE geom && '' || quote_literal(apoint::text)
160                || '' AND ST_Intersects(geom, '' || quote_literal(apoint::text)
161                || '')''
162        LOOP
163                RAISE EXCEPTION
164                ''SQL/MM Spatial exception - edge crosses node.'';
165        END LOOP;
166
167
168        --
169        -- Verify that aface contains apoint
170        -- if aface is null no check is done
171        --
172        IF aface IS NOT NULL THEN
173
174        FOR rec IN EXECUTE ''SELECT ST_Within(''
175                || quote_literal(apoint::text) || ''::geometry,
176                topology.ST_GetFaceGeometry(''
177                || quote_literal(atopology) || '', '' || aface ||
178                '')) As within''
179        LOOP
180                IF rec.within = ''f'' THEN
181                        RAISE EXCEPTION
182                        ''SQL/MM Spatial exception - not within face'';
183                ELSIF rec.within IS NULL THEN
184                        RAISE EXCEPTION
185                        ''SQL/MM Spatial exception - non-existent face'';
186                END IF;
187        END LOOP;
188
189        END IF;
190
191        --
192        -- Get new node id from sequence
193        --
194        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
195                atopology || ''.node_node_id_seq'''')''
196        LOOP
197                nodeid = rec.nextval;
198        END LOOP;
199
200        --
201        -- Insert the new row
202        --
203        IF aface IS NOT NULL THEN
204                EXECUTE ''INSERT INTO '' || quote_ident(atopology)
205                        || ''.node(node_id, geom, containing_face)
206                        VALUES(''||nodeid||'',''||quote_literal(apoint::text)||
207                        '',''||aface||'')'';
208        ELSE
209                EXECUTE ''INSERT INTO '' || quote_ident(atopology)
210                        || ''.node(node_id, geom)
211                        VALUES(''||nodeid||'',''||quote_literal(apoint::text)||
212                        '')'';
213        END IF;
214
215        RETURN nodeid;
216END
217'
218LANGUAGE 'plpgsql' VOLATILE;
219--} ST_AddIsoNode
220
221--{
222-- Topo-Geo and Topo-Net 3: Routine Details
223-- X.3.2
224--
225--  ST_MoveIsoNode(atopology, anode, apoint)
226--
227CREATE OR REPLACE FUNCTION topology.ST_MoveIsoNode(varchar, integer, geometry)
228        RETURNS TEXT AS
229'
230DECLARE
231        atopology ALIAS FOR $1;
232        anode ALIAS FOR $2;
233        apoint ALIAS FOR $3;
234        rec RECORD;
235BEGIN
236
237        --
238        -- All arguments are required
239        --
240        IF atopology IS NULL OR anode IS NULL OR apoint IS NULL THEN
241                RAISE EXCEPTION
242                 ''SQL/MM Spatial exception - null argument'';
243        END IF;
244
245        --
246        -- Apoint must be a point
247        --
248        IF substring(geometrytype(apoint), 1, 5) != ''POINT''
249        THEN
250                RAISE EXCEPTION
251                 ''SQL/MM Spatial exception - invalid point'';
252        END IF;
253
254        --
255        -- Check node isolation.
256        --
257        FOR rec IN EXECUTE ''SELECT edge_id FROM ''
258                || quote_ident(atopology) || ''.edge '' ||
259                '' WHERE start_node =  '' || anode ||
260                '' OR end_node = '' || anode
261        LOOP
262                RAISE EXCEPTION
263                 ''SQL/MM Spatial exception - not isolated node'';
264        END LOOP;
265
266        --
267        -- Check if a coincident node already exists
268        --
269        -- We use index AND x/y equality
270        --
271        FOR rec IN EXECUTE ''SELECT node_id FROM ''
272                || quote_ident(atopology) || ''.node '' ||
273                ''WHERE geom && '' || quote_literal(apoint::text) || ''::geometry''
274                ||'' AND ST_X(geom) = ST_X(''||quote_literal(apoint::text)||''::geometry)''
275                ||'' AND ST_Y(geom) = ST_Y(''||quote_literal(apoint::text)||''::geometry)''
276        LOOP
277                RAISE EXCEPTION
278                 ''SQL/MM Spatial exception - coincident node'';
279        END LOOP;
280
281        --
282        -- Check if any edge crosses (intersects) this node
283        -- I used _intersects_ here to include boundaries (endpoints)
284        --
285        FOR rec IN EXECUTE ''SELECT edge_id FROM ''
286                || quote_ident(atopology) || ''.edge ''
287                || ''WHERE geom && '' || quote_literal(apoint::text)
288                || '' AND ST_Intersects(geom, '' || quote_literal(apoint::text)
289                || '')''
290        LOOP
291                RAISE EXCEPTION
292                ''SQL/MM Spatial exception - edge crosses node.'';
293        END LOOP;
294
295        --
296        -- Update node point
297        --
298        EXECUTE ''UPDATE '' || quote_ident(atopology) || ''.node ''
299                || '' SET geom = '' || quote_literal(apoint::text)
300                || '' WHERE node_id = '' || anode;
301
302        RETURN ''Isolated Node '' || anode || '' moved to location ''
303                || ST_X(apoint) || '','' || ST_Y(apoint);
304END
305'
306LANGUAGE 'plpgsql' VOLATILE;
307--} ST_MoveIsoNode
308
309--{
310-- Topo-Geo and Topo-Net 3: Routine Details
311-- X.3.3
312--
313--  ST_RemoveIsoNode(atopology, anode)
314--
315CREATE OR REPLACE FUNCTION topology.ST_RemoveIsoNode(varchar, integer)
316        RETURNS TEXT AS
317'
318DECLARE
319        atopology ALIAS FOR $1;
320        anode ALIAS FOR $2;
321        rec RECORD;
322BEGIN
323
324        --
325        -- Atopology and apoint are required
326        --
327        IF atopology IS NULL OR anode IS NULL THEN
328                RAISE EXCEPTION
329                 ''SQL/MM Spatial exception - null argument'';
330        END IF;
331
332        --
333        -- Check node isolation.
334        --
335        FOR rec IN EXECUTE ''SELECT edge_id FROM ''
336                || quote_ident(atopology) || ''.edge_data '' ||
337                '' WHERE start_node =  '' || anode ||
338                '' OR end_node = '' || anode
339        LOOP
340                RAISE EXCEPTION
341                 ''SQL/MM Spatial exception - not isolated node'';
342        END LOOP;
343
344        EXECUTE ''DELETE FROM '' || quote_ident(atopology) || ''.node ''
345                || '' WHERE node_id = '' || anode;
346
347        RETURN ''Isolated node '' || anode || '' removed'';
348END
349'
350LANGUAGE 'plpgsql' VOLATILE;
351--} ST_RemoveIsoNode
352
353--{
354-- Topo-Geo and Topo-Net 3: Routine Details
355-- X.3.7
356--
357--  ST_RemoveIsoEdge(atopology, anedge)
358--
359CREATE OR REPLACE FUNCTION topology.ST_RemoveIsoEdge(varchar, integer)
360        RETURNS TEXT AS
361'
362DECLARE
363        atopology ALIAS FOR $1;
364        anedge ALIAS FOR $2;
365        edge RECORD;
366        rec RECORD;
367        ok BOOL;
368BEGIN
369
370        --
371        -- Atopology and anedge are required
372        --
373        IF atopology IS NULL OR anedge IS NULL THEN
374                RAISE EXCEPTION
375                 ''SQL/MM Spatial exception - null argument'';
376        END IF;
377
378        --
379        -- Check node existance
380        --
381        ok = false;
382        FOR edge IN EXECUTE ''SELECT * FROM ''
383                || quote_ident(atopology) || ''.edge_data '' ||
384                '' WHERE edge_id =  '' || anedge
385        LOOP
386                ok = true;
387        END LOOP;
388        IF NOT ok THEN
389                RAISE EXCEPTION
390                  ''SQL/MM Spatial exception - non-existent edge'';
391        END IF;
392
393        --
394        -- Check node isolation
395        --
396        IF edge.left_face != edge.right_face THEN
397                RAISE EXCEPTION
398                  ''SQL/MM Spatial exception - not isolated edge'';
399        END IF;
400
401        FOR rec IN EXECUTE ''SELECT * FROM ''
402                || quote_ident(atopology) || ''.edge_data ''
403                || '' WHERE edge_id !=  '' || anedge
404                || '' AND ( start_node = '' || edge.start_node
405                || '' OR start_node = '' || edge.end_node
406                || '' OR end_node = '' || edge.start_node
407                || '' OR end_node = '' || edge.end_node
408                || '' ) ''
409        LOOP
410                RAISE EXCEPTION
411                  ''SQL/MM Spatial exception - not isolated edge'';
412        END LOOP;
413
414        --
415        -- Delete the edge
416        --
417        EXECUTE ''DELETE FROM '' || quote_ident(atopology) || ''.edge_data ''
418                || '' WHERE edge_id = '' || anedge;
419
420        RETURN ''Isolated edge '' || anedge || '' removed'';
421END
422'
423LANGUAGE 'plpgsql' VOLATILE;
424--} ST_RemoveIsoEdge
425
426--{
427-- Topo-Geo and Topo-Net 3: Routine Details
428-- X.3.8
429--
430--  ST_NewEdgesSplit(atopology, anedge, apoint)
431--
432CREATE OR REPLACE FUNCTION topology.ST_NewEdgesSplit(varchar, integer, geometry)
433        RETURNS INTEGER AS
434'
435DECLARE
436        atopology ALIAS FOR $1;
437        anedge ALIAS FOR $2;
438        apoint ALIAS FOR $3;
439        oldedge RECORD;
440        rec RECORD;
441        tmp integer;
442        topoid integer;
443        nodeid integer;
444        nodepos float8;
445        edgeid1 integer;
446        edgeid2 integer;
447        edge1 geometry;
448        edge2 geometry;
449        ok BOOL;
450BEGIN
451
452        --
453        -- All args required
454        --
455        IF atopology IS NULL OR anedge IS NULL OR apoint IS NULL THEN
456                RAISE EXCEPTION
457                 ''SQL/MM Spatial exception - null argument'';
458        END IF;
459
460        --
461        -- Check node existance
462        --
463        ok = false;
464        FOR oldedge IN EXECUTE ''SELECT * FROM ''
465                || quote_ident(atopology) || ''.edge_data '' ||
466                '' WHERE edge_id =  '' || anedge
467        LOOP
468                ok = true;
469        END LOOP;
470        IF NOT ok THEN
471                RAISE EXCEPTION
472                  ''SQL/MM Spatial exception - non-existent edge'';
473        END IF;
474
475        --
476        -- Check that given point is Within(anedge.geom)
477        --
478        IF NOT ST_Within(apoint, oldedge.geom) THEN
479                RAISE EXCEPTION
480                  ''SQL/MM Spatial exception - point not on edge'';
481        END IF;
482
483        --
484        -- Check if a coincident node already exists
485        --
486        FOR rec IN EXECUTE ''SELECT node_id FROM ''
487                || quote_ident(atopology) || ''.node ''
488                || ''WHERE geom && ''
489                || quote_literal(apoint::text) || ''::geometry''
490                || '' AND ST_X(geom) = ST_X(''
491                || quote_literal(apoint::text) || ''::geometry)''
492                || '' AND ST_Y(geom) = ST_Y(''
493                || quote_literal(apoint::text) || ''::geometry)''
494        LOOP
495                RAISE EXCEPTION
496                 ''SQL/MM Spatial exception - coincident node'';
497        END LOOP;
498
499        --
500        -- Get new node id
501        --
502        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
503                atopology || ''.node_node_id_seq'''')''
504        LOOP
505                nodeid = rec.nextval;
506        END LOOP;
507
508        --RAISE NOTICE ''Next node id = % '', nodeid;
509
510        --
511        -- Add the new node
512        --
513        EXECUTE ''INSERT INTO '' || quote_ident(atopology)
514                || ''.node(node_id, geom)
515                VALUES('' || nodeid || '',''
516                || quote_literal(apoint::text)
517                || '')'';
518
519        --
520        -- Delete the old edge
521        --
522        EXECUTE ''DELETE FROM '' || quote_ident(atopology) || ''.edge_data ''
523                || '' WHERE edge_id = '' || anedge;
524
525        --
526        -- Compute new edges
527        --
528        nodepos = ST_Line_locate_point(oldedge.geom, apoint);
529        edge1 = ST_Line_substring(oldedge.geom, 0, nodepos);
530        edge2 = ST_Line_substring(oldedge.geom, nodepos, 1);
531
532        --
533        -- Get ids for the new edges
534        --
535        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
536                atopology || ''.edge_data_edge_id_seq'''')''
537        LOOP
538                edgeid1 = rec.nextval;
539        END LOOP;
540        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
541                atopology || ''.edge_data_edge_id_seq'''')''
542        LOOP
543                edgeid2 = rec.nextval;
544        END LOOP;
545
546        --RAISE NOTICE ''EdgeId1 % EdgeId2 %'', edgeid1, edgeid2;
547
548        --
549        -- Insert the two new edges
550        --
551        EXECUTE ''INSERT INTO '' || quote_ident(atopology)
552                || ''.edge VALUES(''
553                ||edgeid1||'',''||oldedge.start_node
554                ||'',''||nodeid
555                ||'',''||edgeid2
556                ||'',''||oldedge.next_right_edge
557                ||'',''||oldedge.left_face
558                ||'',''||oldedge.right_face
559                ||'',''||quote_literal(edge1::text)
560                ||'')'';
561
562        EXECUTE ''INSERT INTO '' || quote_ident(atopology)
563                || ''.edge VALUES(''
564                ||edgeid2||'',''||nodeid
565                ||'',''||oldedge.end_node
566                ||'',''||oldedge.next_left_edge
567                ||'',-''||edgeid1
568                ||'',''||oldedge.left_face
569                ||'',''||oldedge.right_face
570                ||'',''||quote_literal(edge2::text)
571                ||'')'';
572
573        --
574        -- Update all next edge references to match new layout
575        --
576
577        EXECUTE ''UPDATE '' || quote_ident(atopology)
578                || ''.edge_data SET next_right_edge = ''
579                || edgeid2
580                || '',''
581                || '' abs_next_right_edge = '' || edgeid2
582                || '' WHERE next_right_edge = '' || anedge;
583        EXECUTE ''UPDATE '' || quote_ident(atopology)
584                || ''.edge_data SET next_right_edge = ''
585                || -edgeid1
586                || '',''
587                || '' abs_next_right_edge = '' || edgeid1
588                || '' WHERE next_right_edge = '' || -anedge;
589
590        EXECUTE ''UPDATE '' || quote_ident(atopology)
591                || ''.edge_data SET next_left_edge = ''
592                || edgeid1
593                || '',''
594                || '' abs_next_left_edge = '' || edgeid1
595                || '' WHERE next_left_edge = '' || anedge;
596        EXECUTE ''UPDATE '' || quote_ident(atopology)
597                || ''.edge_data SET ''
598                || '' next_left_edge = '' || -edgeid2
599                || '',''
600                || '' abs_next_left_edge = '' || edgeid2
601                || '' WHERE next_left_edge = '' || -anedge;
602
603        -- Get topology id
604        SELECT id FROM topology.topology into topoid
605                WHERE name = atopology;
606        IF topoid IS NULL THEN
607                RAISE EXCEPTION ''No topology % registered'',
608                        quote_ident(atopology);
609        END IF;
610
611        --
612        -- Update references in the Relation table.
613        -- We only take into considerations non-hierarchical
614        -- TopoGeometry here, for obvious reasons.
615        --
616        FOR rec IN EXECUTE ''SELECT r.* FROM ''
617                || quote_ident(atopology)
618                || ''.relation r, topology.layer l ''
619                || '' WHERE ''
620                || '' l.topology_id = '' || topoid
621                || '' AND l.level = 0 ''
622                || '' AND l.layer_id = r.layer_id ''
623                || '' AND abs(r.element_id) = '' || anedge
624                || '' AND r.element_type = 2''
625        LOOP
626                --RAISE NOTICE ''TopoGeometry % in layer % contains the edge being split'', rec.topogeo_id, rec.layer_id;
627
628                -- Delete old reference
629                EXECUTE ''DELETE FROM '' || quote_ident(atopology)
630                        || ''.relation ''
631                        || '' WHERE ''
632                        || ''layer_id = '' || rec.layer_id
633                        || '' AND ''
634                        || ''topogeo_id = '' || rec.topogeo_id
635                        || '' AND ''
636                        || ''element_type = '' || rec.element_type
637                        || '' AND ''
638                        || ''abs(element_id) = '' || anedge;
639
640                -- Add new reference to edge1
641                IF rec.element_id < 0 THEN
642                        tmp = -edgeid1;
643                ELSE
644                        tmp = edgeid1;
645                END IF;
646                EXECUTE ''INSERT INTO '' || quote_ident(atopology)
647                        || ''.relation ''
648                        || '' VALUES( ''
649                        || rec.topogeo_id
650                        || '',''
651                        || rec.layer_id
652                        || '',''
653                        || tmp
654                        || '',''
655                        || rec.element_type
656                        || '')'';
657
658                -- Add new reference to edge2
659                IF rec.element_id < 0 THEN
660                        tmp = -edgeid2;
661                ELSE
662                        tmp = edgeid2;
663                END IF;
664                EXECUTE ''INSERT INTO '' || quote_ident(atopology)
665                        || ''.relation ''
666                        || '' VALUES( ''
667                        || rec.topogeo_id
668                        || '',''
669                        || rec.layer_id
670                        || '',''
671                        || tmp
672                        || '',''
673                        || rec.element_type
674                        || '')'';
675                       
676        END LOOP;
677
678        --RAISE NOTICE ''Edge % split in edges % and % by node %'',
679        --      anedge, edgeid1, edgeid2, nodeid;
680
681        RETURN nodeid;
682END
683'
684LANGUAGE 'plpgsql' VOLATILE;
685--} ST_NewEdgesSplit
686
687--{
688-- Topo-Geo and Topo-Net 3: Routine Details
689-- X.3.9
690--
691--  ST_ModEdgesSplit(atopology, anedge, apoint)
692--
693CREATE OR REPLACE FUNCTION topology.ST_ModEdgesSplit(varchar, integer, geometry)
694        RETURNS INTEGER AS
695'
696DECLARE
697        atopology ALIAS FOR $1;
698        anedge ALIAS FOR $2;
699        apoint ALIAS FOR $3;
700        oldedge RECORD;
701        rec RECORD;
702        tmp integer;
703        topoid integer;
704        nodeid integer;
705        nodepos float8;
706        newedgeid integer;
707        newedge1 geometry;
708        newedge2 geometry;
709        query text;
710        ok BOOL;
711BEGIN
712
713        --
714        -- All args required
715        --
716        IF atopology IS NULL OR anedge IS NULL OR apoint IS NULL THEN
717                RAISE EXCEPTION
718                 ''SQL/MM Spatial exception - null argument'';
719        END IF;
720
721        --
722        -- Check node existance
723        --
724        ok = false;
725        FOR oldedge IN EXECUTE ''SELECT * FROM ''
726                || quote_ident(atopology) || ''.edge_data '' ||
727                '' WHERE edge_id =  '' || anedge
728        LOOP
729                ok = true;
730        END LOOP;
731        IF NOT ok THEN
732                RAISE EXCEPTION
733                  ''SQL/MM Spatial exception - non-existent edge'';
734        END IF;
735
736        --
737        -- Check that given point is Within(anedge.geom)
738        --
739        IF NOT ST_Within(apoint, oldedge.geom) THEN
740                RAISE EXCEPTION
741                  ''SQL/MM Spatial exception - point not on edge'';
742        END IF;
743
744        --
745        -- Check if a coincident node already exists
746        --
747        FOR rec IN EXECUTE ''SELECT node_id FROM ''
748                || quote_ident(atopology) || ''.node '' ||
749                ''WHERE geom && ''
750                || quote_literal(apoint::text) || ''::geometry''
751                ||'' AND ST_X(geom) = ST_X(''
752                || quote_literal(apoint::text) || ''::geometry)''
753                ||'' AND ST_Y(geom) = ST_Y(''
754                ||quote_literal(apoint::text)||''::geometry)''
755        LOOP
756                RAISE EXCEPTION
757                 ''SQL/MM Spatial exception - coincident node'';
758        END LOOP;
759
760        --
761        -- Get new node id
762        --
763        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
764                atopology || ''.node_node_id_seq'''')''
765        LOOP
766                nodeid = rec.nextval;
767        END LOOP;
768
769        --RAISE NOTICE ''Next node id = % '', nodeid;
770
771        --
772        -- Add the new node
773        --
774        EXECUTE ''INSERT INTO '' || quote_ident(atopology)
775                || ''.node(node_id, geom)
776                VALUES(''||nodeid||'',''||quote_literal(apoint::text)||
777                '')'';
778
779        --
780        -- Compute new edge
781        --
782        nodepos = line_locate_point(oldedge.geom, apoint);
783        newedge1 = line_substring(oldedge.geom, 0, nodepos);
784        newedge2 = line_substring(oldedge.geom, nodepos, 1);
785
786
787        --
788        -- Get ids for the new edge
789        --
790        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
791                atopology || ''.edge_data_edge_id_seq'''')''
792        LOOP
793                newedgeid = rec.nextval;
794        END LOOP;
795
796        --
797        -- Insert the new edge
798        --
799        EXECUTE ''INSERT INTO '' || quote_ident(atopology)
800                || ''.edge ''
801                || ''(edge_id, start_node, end_node,''
802                || ''next_left_edge, next_right_edge,''
803                || ''left_face, right_face, geom) ''
804                || ''VALUES(''
805                ||newedgeid||'',''||nodeid
806                ||'',''||oldedge.end_node
807                ||'',''||oldedge.next_left_edge
808                ||'',-''||anedge
809                ||'',''||oldedge.left_face
810                ||'',''||oldedge.right_face
811                ||'',''||quote_literal(newedge2::text)
812                ||'')'';
813
814        --
815        -- Update the old edge
816        --
817        EXECUTE ''UPDATE '' || quote_ident(atopology) || ''.edge_data ''
818                || '' SET geom = '' || quote_literal(newedge1::text)
819                || '',''
820                || '' next_left_edge = '' || newedgeid
821                || '',''
822                || '' end_node = '' || nodeid
823                || '' WHERE edge_id = '' || anedge;
824
825
826        --
827        -- Update all next edge references to match new layout
828        --
829
830        EXECUTE ''UPDATE '' || quote_ident(atopology)
831                || ''.edge_data SET next_right_edge = ''
832                || -newedgeid
833                || '',''
834                || '' abs_next_right_edge = '' || newedgeid
835                || '' WHERE next_right_edge = '' || -anedge;
836
837        EXECUTE ''UPDATE '' || quote_ident(atopology)
838                || ''.edge_data SET ''
839                || '' next_left_edge = '' || -newedgeid
840                || '',''
841                || '' abs_next_left_edge = '' || newedgeid
842                || '' WHERE next_left_edge = '' || -anedge;
843
844        -- Get topology id
845        SELECT id FROM topology.topology into topoid
846                WHERE name = atopology;
847
848        --
849        -- Update references in the Relation table.
850        -- We only take into considerations non-hierarchical
851        -- TopoGeometry here, for obvious reasons.
852        --
853        FOR rec IN EXECUTE ''SELECT r.* FROM ''
854                || quote_ident(atopology)
855                || ''.relation r, topology.layer l ''
856                || '' WHERE ''
857                || '' l.topology_id = '' || topoid
858                || '' AND l.level = 0 ''
859                || '' AND l.layer_id = r.layer_id ''
860                || '' AND abs(r.element_id) = '' || anedge
861                || '' AND r.element_type = 2''
862        LOOP
863                --RAISE NOTICE ''TopoGeometry % in layer % contains the edge being split (%) - updating to add new edge %'', rec.topogeo_id, rec.layer_id, anedge, newedgeid;
864
865                -- Add new reference to edge1
866                IF rec.element_id < 0 THEN
867                        tmp = -newedgeid;
868                ELSE
869                        tmp = newedgeid;
870                END IF;
871                query = ''INSERT INTO '' || quote_ident(atopology)
872                        || ''.relation ''
873                        || '' VALUES( ''
874                        || rec.topogeo_id
875                        || '',''
876                        || rec.layer_id
877                        || '',''
878                        || tmp
879                        || '',''
880                        || rec.element_type
881                        || '')'';
882
883                --RAISE NOTICE ''%'', query;
884                EXECUTE query;
885        END LOOP;
886
887        --RAISE NOTICE ''Edge % split in edges % and % by node %'',
888        --      anedge, anedge, newedgeid, nodeid;
889
890        RETURN nodeid;
891END
892'
893LANGUAGE 'plpgsql' VOLATILE;
894--} ST_ModEdgesSplit
895
896--{
897-- Topo-Geo and Topo-Net 3: Routine Details
898-- X.3.4
899--
900--  ST_AddIsoEdge(atopology, anode, anothernode, acurve)
901--
902CREATE OR REPLACE FUNCTION topology.ST_AddIsoEdge(varchar, integer, integer, geometry)
903        RETURNS INTEGER AS
904'
905DECLARE
906        atopology ALIAS FOR $1;
907        anode ALIAS FOR $2;
908        anothernode ALIAS FOR $3;
909        acurve ALIAS FOR $4;
910        aface INTEGER;
911        face GEOMETRY;
912        snodegeom GEOMETRY;
913        enodegeom GEOMETRY;
914        count INTEGER;
915        rec RECORD;
916        edgeid INTEGER;
917BEGIN
918
919        --
920        -- All arguments required
921        --
922        IF atopology IS NULL
923           OR anode IS NULL
924           OR anothernode IS NULL
925           OR acurve IS NULL
926        THEN
927                RAISE EXCEPTION
928                 ''SQL/MM Spatial exception - null argument'';
929        END IF;
930
931        --
932        -- Acurve must be a LINESTRING
933        --
934        IF substring(geometrytype(acurve), 1, 4) != ''LINE''
935        THEN
936                RAISE EXCEPTION
937                 ''SQL/MM Spatial exception - invalid curve'';
938        END IF;
939
940        --
941        -- Acurve must be a simple
942        --
943        IF NOT ST_IsSimple(acurve)
944        THEN
945                RAISE EXCEPTION
946                 ''SQL/MM Spatial exception - curve not simple'';
947        END IF;
948
949        --
950        -- Check for:
951        --    existence of nodes
952        --    nodes faces match
953        -- Extract:
954        --    nodes face id
955        --    nodes geoms
956        --
957        aface := NULL;
958        count := 0;
959        FOR rec IN EXECUTE ''SELECT geom, containing_face, node_id FROM ''
960                || quote_ident(atopology) || ''.node
961                WHERE node_id = '' || anode ||
962                '' OR node_id = '' || anothernode
963        LOOP
964                IF count > 0 AND aface != rec.containing_face THEN
965                        RAISE EXCEPTION
966                        ''SQL/MM Spatial exception - nodes in different faces'';
967                ELSE
968                        aface := rec.containing_face;
969                END IF;
970
971                -- Get nodes geom
972                IF rec.node_id = anode THEN
973                        snodegeom = rec.geom;
974                ELSE
975                        enodegeom = rec.geom;
976                END IF;
977
978                count = count+1;
979
980        END LOOP;
981        IF count < 2 THEN
982                RAISE EXCEPTION
983                 ''SQL/MM Spatial exception - non-existent node'';
984        END IF;
985
986
987        --
988        -- Check nodes isolation.
989        --
990        FOR rec IN EXECUTE ''SELECT edge_id FROM ''
991                || quote_ident(atopology) || ''.edge_data '' ||
992                '' WHERE start_node =  '' || anode ||
993                '' OR end_node = '' || anode ||
994                '' OR start_node = '' || anothernode ||
995                '' OR end_node = '' || anothernode
996        LOOP
997                RAISE EXCEPTION
998                 ''SQL/MM Spatial exception - not isolated node'';
999        END LOOP;
1000
1001        --
1002        -- Check acurve to be within endpoints containing face
1003        -- (unless it is the world face, I suppose)
1004        --
1005        IF aface IS NOT NULL THEN
1006
1007                --
1008                -- Extract endpoints face geometry
1009                --
1010                FOR rec IN EXECUTE ''SELECT topology.ST_GetFaceGeometry(''
1011                        || quote_literal(atopology) ||
1012                        '','' || aface || '') as face''
1013                LOOP
1014                        face := rec.face;
1015                END LOOP;
1016
1017                --
1018                -- Check acurve to be within face
1019                --
1020                IF ! ST_Within(acurve, face) THEN
1021        RAISE EXCEPTION
1022        ''SQL/MM Spatial exception - geometry not within face.'';
1023                END IF;
1024
1025        END IF;
1026
1027        --
1028        -- l) Check that start point of acurve match start node
1029        -- geoms.
1030        --
1031        IF ST_X(snodegeom) != ST_X(ST_StartPoint(acurve)) OR
1032           ST_Y(snodegeom) != ST_Y(ST_StartPoint(acurve)) THEN
1033  RAISE EXCEPTION
1034  ''SQL/MM Spatial exception - start node not geometry start point.'';
1035        END IF;
1036
1037        --
1038        -- m) Check that end point of acurve match end node
1039        -- geoms.
1040        --
1041        IF ST_X(enodegeom) != ST_X(ST_EndPoint(acurve)) OR
1042           ST_Y(enodegeom) != ST_Y(ST_EndPoint(acurve)) THEN
1043  RAISE EXCEPTION
1044  ''SQL/MM Spatial exception - end node not geometry end point.'';
1045        END IF;
1046
1047        --
1048        -- n) Check if curve crosses (contains) any node
1049        -- I used _contains_ here to leave endpoints out
1050        --
1051        FOR rec IN EXECUTE ''SELECT node_id FROM ''
1052                || quote_ident(atopology) || ''.node ''
1053                || '' WHERE geom && '' || quote_literal(acurve::text)
1054                || '' AND ST_Contains('' || quote_literal(acurve::text)
1055                || '',geom)''
1056        LOOP
1057                RAISE EXCEPTION
1058                ''SQL/MM Spatial exception - geometry crosses a node'';
1059        END LOOP;
1060
1061        --
1062        -- o) Check if curve intersects any other edge
1063        --
1064        FOR rec IN EXECUTE ''SELECT * FROM ''
1065                || quote_ident(atopology) || ''.edge_data
1066                WHERE geom && '' || quote_literal(acurve::text) || ''::geometry
1067                AND ST_Intersects(geom, '' || quote_literal(acurve::text) || ''::geometry)''
1068        LOOP
1069                RAISE EXCEPTION
1070                ''SQL/MM Spatial exception - geometry intersects an edge'';
1071        END LOOP;
1072
1073        --
1074        -- Get new edge id from sequence
1075        --
1076        FOR rec IN EXECUTE ''SELECT nextval('''''' ||
1077                atopology || ''.edge_data_edge_id_seq'''')''
1078        LOOP
1079                edgeid = rec.nextval;
1080        END LOOP;
1081
1082        --
1083        -- Insert the new row
1084        --
1085        IF aface IS NULL THEN aface := 0; END IF;
1086
1087        EXECUTE ''INSERT INTO '' || quote_ident(atopology)
1088                || ''.edge VALUES(''||edgeid||'',''||anode||
1089                        '',''||anothernode||'',''
1090                        ||(-edgeid)||'',''||edgeid||'',''
1091                        ||aface||'',''||aface||'',''
1092                        ||quote_literal(acurve::text)||'')'';
1093
1094        RETURN edgeid;
1095
1096END
1097'
1098LANGUAGE 'plpgsql' VOLATILE;
1099--} ST_AddIsoEdge
1100
1101--{
1102-- Topo-Geo and Topo-Net 3: Routine Details
1103-- X.3.6
1104--
1105--  ST_ChangeEdgeGeom(atopology, anedge, acurve)
1106--
1107CREATE OR REPLACE FUNCTION topology.ST_ChangeEdgeGeom(varchar, integer, geometry)
1108        RETURNS TEXT AS
1109'
1110DECLARE
1111        atopology ALIAS FOR $1;
1112        anedge ALIAS FOR $2;
1113        acurve ALIAS FOR $3;
1114        aface INTEGER;
1115        face GEOMETRY;
1116        snodegeom GEOMETRY;
1117        enodegeom GEOMETRY;
1118        count INTEGER;
1119        rec RECORD;
1120        edgeid INTEGER;
1121        oldedge RECORD;
1122BEGIN
1123
1124        --
1125        -- All arguments required
1126        --
1127        IF atopology IS NULL
1128           OR anedge IS NULL
1129           OR acurve IS NULL
1130        THEN
1131                RAISE EXCEPTION
1132                 ''SQL/MM Spatial exception - null argument'';
1133        END IF;
1134
1135        --
1136        -- Acurve must be a LINESTRING
1137        --
1138        IF substring(geometrytype(acurve), 1, 4) != ''LINE''
1139        THEN
1140                RAISE EXCEPTION
1141                 ''SQL/MM Spatial exception - invalid curve'';
1142        END IF;
1143
1144        --
1145        -- Acurve must be a simple
1146        --
1147        IF NOT ST_IsSimple(acurve)
1148        THEN
1149                RAISE EXCEPTION
1150                 ''SQL/MM Spatial exception - curve not simple'';
1151        END IF;
1152
1153        --
1154        -- e) Check StartPoint consistency
1155        --
1156        FOR rec IN EXECUTE ''SELECT * FROM ''
1157                || quote_ident(atopology) || ''.edge_data e, ''
1158                || quote_ident(atopology) || ''.node n ''
1159                || '' WHERE e.edge_id = '' || anedge
1160                || '' AND n.node_id = e.start_node ''
1161                || '' AND ( ST_X(n.geom) != ''
1162                || ST_X(ST_StartPoint(acurve))
1163                || '' OR ST_Y(n.geom) != ''
1164                || ST_Y(ST_StartPoint(acurve))
1165                || '')''
1166        LOOP
1167                RAISE EXCEPTION
1168                ''SQL/MM Spatial exception - start node not geometry start point.'';
1169        END LOOP;
1170
1171        --
1172        -- f) Check EndPoint consistency
1173        --
1174        FOR rec IN EXECUTE ''SELECT * FROM ''
1175                || quote_ident(atopology) || ''.edge_data e, ''
1176                || quote_ident(atopology) || ''.node n ''
1177                || '' WHERE e.edge_id = '' || anedge
1178                || '' AND n.node_id = e.end_node ''
1179                || '' AND ( ST_X(n.geom) != ''
1180                || ST_X(ST_EndPoint(acurve))
1181                || '' OR ST_Y(n.geom) != ''
1182                || ST_Y(ST_EndPoint(acurve))
1183                || '')''
1184        LOOP
1185                RAISE EXCEPTION
1186                ''SQL/MM Spatial exception - end node not geometry end point.'';
1187        END LOOP;
1188
1189        --
1190        -- g) Check if curve crosses any node
1191        -- _within_ used to let endpoints out
1192        --
1193        FOR rec IN EXECUTE ''SELECT node_id FROM ''
1194                || quote_ident(atopology) || ''.node
1195                WHERE geom && '' || quote_literal(acurve::text) || ''::geometry
1196                AND ST_Within(geom, '' || quote_literal(acurve::text) || ''::geometry)''
1197        LOOP
1198                RAISE EXCEPTION
1199                ''SQL/MM Spatial exception - geometry crosses a node'';
1200        END LOOP;
1201
1202        --
1203        -- h) Check if curve intersects any other edge
1204        --
1205        FOR rec IN EXECUTE ''SELECT * FROM ''
1206                || quote_ident(atopology) || ''.edge_data ''
1207                || '' WHERE edge_id != '' || anedge
1208                || '' AND geom && ''
1209                || quote_literal(acurve::text) || ''::geometry ''
1210                || '' AND ST_Intersects(geom, ''
1211                || quote_literal(acurve::text) || ''::geometry)''
1212        LOOP
1213                RAISE EXCEPTION
1214                ''SQL/MM Spatial exception - geometry intersects an edge'';
1215        END LOOP;
1216
1217        --
1218        -- Update edge geometry
1219        --
1220        EXECUTE ''UPDATE '' || quote_ident(atopology) || ''.edge_data ''
1221                || '' SET geom = '' || quote_literal(acurve::text)
1222                || '' WHERE edge_id = '' || anedge;
1223
1224        RETURN ''Edge '' || anedge || '' changed'';
1225
1226END
1227'
1228LANGUAGE 'plpgsql' VOLATILE;
1229--} ST_ChangeEdgeGeom
1230
1231--{
1232-- Topo-Geo and Topo-Net 3: Routine Details
1233-- X.3.12
1234--
1235--  ST_AddEdgeNewFaces(atopology, anode, anothernode, acurve)
1236--
1237CREATE OR REPLACE FUNCTION topology.ST_AddEdgeNewFaces(varchar, integer, integer, geometry)
1238        RETURNS INTEGER AS
1239'
1240DECLARE
1241        atopology ALIAS FOR $1;
1242        anode ALIAS FOR $2;
1243        anothernode ALIAS FOR $3;
1244        acurve ALIAS FOR $4;
1245        rec RECORD;
1246        i INTEGER;
1247        az FLOAT8;
1248        azdif FLOAT8;
1249        myaz FLOAT8;
1250        minazimuth FLOAT8;
1251        maxazimuth FLOAT8;
1252        p2 GEOMETRY;
1253BEGIN
1254
1255        --
1256        -- All args required
1257        --
1258        IF atopology IS NULL
1259                OR anode IS NULL
1260                OR anothernode IS NULL
1261                OR acurve IS NULL
1262        THEN
1263                RAISE EXCEPTION ''SQL/MM Spatial exception - null argument'';
1264        END IF;
1265
1266        --
1267        -- Acurve must be a LINESTRING
1268        --
1269        IF substring(geometrytype(acurve), 1, 4) != ''LINE''
1270        THEN
1271                RAISE EXCEPTION
1272                 ''SQL/MM Spatial exception - invalid curve'';
1273        END IF;
1274       
1275        --
1276        -- Curve must be simple
1277        --
1278        IF NOT ST_IsSimple(acurve) THEN
1279                RAISE EXCEPTION
1280                 ''SQL/MM Spatial exception - curve not simple'';
1281        END IF;
1282
1283        --
1284        -- Check endpoints existance and match with Curve geometry
1285        --
1286        i=0;
1287        FOR rec IN EXECUTE ''SELECT ''
1288                || '' CASE WHEN node_id = '' || anode
1289                || '' THEN 1 WHEN node_id = '' || anothernode
1290                || '' THEN 0 END AS start, geom FROM ''
1291                || quote_ident(atopology)
1292                || ''.node ''
1293                || '' WHERE node_id IN ( ''
1294                || anode || '','' || anothernode
1295                || '')''
1296        LOOP
1297                IF rec.start THEN
1298                        IF NOT Equals(rec.geom, ST_StartPoint(acurve))
1299                        THEN
1300        RAISE EXCEPTION
1301        ''SQL/MM Spatial exception - start node not geometry start point.'';
1302                        END IF;
1303                ELSE
1304                        IF NOT Equals(rec.geom, ST_EndPoint(acurve))
1305                        THEN
1306        RAISE EXCEPTION
1307        ''SQL/MM Spatial exception - end node not geometry end point.'';
1308                        END IF;
1309                END IF;
1310
1311                i=i+1;
1312        END LOOP;
1313
1314        IF i < 2 THEN
1315                RAISE EXCEPTION
1316                 ''SQL/MM Spatial exception - non-existent node'';
1317        END IF;
1318
1319        --
1320        -- Check if this geometry crosses any node
1321        --
1322        FOR rec IN EXECUTE ''SELECT node_id FROM ''
1323                || quote_ident(atopology) || ''.node
1324                WHERE geom && '' || quote_literal(acurve::text) || ''::geometry
1325                AND ST_Within(geom, '' || quote_literal(acurve::text) || ''::geometry)''
1326        LOOP
1327                RAISE EXCEPTION
1328                ''SQL/MM Spatial exception - geometry crosses a node'';
1329        END LOOP;
1330
1331        --
1332        -- Check if this geometry crosses any existing edge
1333        --
1334        FOR rec IN EXECUTE ''SELECT * FROM ''
1335                || quote_ident(atopology) || ''.edge_data
1336                WHERE geom && '' || quote_literal(acurve::text) || ''::geometry
1337                AND crosses(geom, '' || quote_literal(acurve::text) || ''::geometry)''
1338        LOOP
1339                RAISE EXCEPTION
1340                ''SQL/MM Spatial exception - geometry crosses an edge'';
1341        END LOOP;
1342
1343        --
1344        -- Check if another edge share this edge endpoints
1345        --
1346        FOR rec IN EXECUTE ''SELECT * FROM ''
1347                || quote_ident(atopology) || ''.edge_data ''
1348                || '' WHERE ''
1349                || '' geom && '' || quote_literal(acurve::text) || ''::geometry ''
1350                || '' AND ''
1351                || '' ( (''
1352                || '' start_node = '' || anode
1353                || '' AND ''
1354                || '' end_node = '' || anothernode
1355                || '' ) OR ( ''
1356                || '' end_node = '' || anode
1357                || '' AND ''
1358                || '' start_node = '' || anothernode
1359                || '' ) )''
1360                || '' AND ''
1361                || ''equals(geom,'' || quote_literal(acurve::text) || ''::geometry)''
1362        LOOP
1363                RAISE EXCEPTION
1364                ''SQL/MM Spatial exception - coincident edge'';
1365        END LOOP;
1366
1367        ---------------------------------------------------------------
1368        --
1369        -- All checks passed, time to extract informations about
1370        -- endpoints:
1371        --
1372        --      next_left_edge
1373        --      next_right_edge
1374        --      left_face
1375        --      right_face
1376        --
1377        ---------------------------------------------------------------
1378
1379        --
1380        --
1381        -- Compute next_left_edge
1382        --
1383        -- We fetch all edges with an endnode equal to
1384        -- this edge end_node (anothernode).
1385        -- For each edge we compute azimuth of the segment(s).
1386        -- Of interest are the edges with closest (smaller
1387        -- and bigger) azimuths then the azimuth of
1388        -- this edge last segment.
1389        --
1390
1391        myaz = azimuth(ST_EndPoint(acurve), ST_PointN(acurve, NumPoints(acurve)-1));
1392        RAISE NOTICE ''My end-segment azimuth: %'', myaz;
1393        FOR rec IN EXECUTE ''SELECT ''
1394                || ''edge_id, end_node, start_node, geom''
1395                || '' FROM ''
1396                || quote_ident(atopology)
1397                || ''.edge_data ''
1398                || '' WHERE ''
1399                || '' end_node = '' || anothernode
1400                || '' OR ''
1401                || '' start_node = '' || anothernode
1402        LOOP
1403
1404                IF rec.start_node = anothernode THEN
1405                        --
1406                        -- Edge starts at our node, we compute
1407                        -- azimuth from node to its second point
1408                        --
1409                        az = ST_Azimuth(ST_EndPoint(acurve),
1410                                ST_PointN(rec.geom, 2));
1411
1412                        RAISE NOTICE ''Edge % starts at node % - azimuth %'',
1413                                rec.edge_id, rec.start_node, az;
1414                END IF;
1415
1416                IF rec.end_node = anothernode THEN
1417                        --
1418                        -- Edge ends at our node, we compute
1419                        -- azimuth from node to its second-last point
1420                        --
1421                        az = ST_Azimuth(ST_EndPoint(acurve),
1422                                ST_PointN(rec.geom, ST_NumPoints(rec.geom)-1));
1423
1424                        RAISE NOTICE ''Edge % ends at node % - azimuth %'',
1425                                rec.edge_id, rec.end_node, az;
1426                END IF;
1427        END LOOP;
1428
1429
1430        RAISE EXCEPTION ''Not implemented yet'';
1431END
1432'
1433LANGUAGE 'plpgsql' VOLATILE;
1434--} ST_AddEdgeNewFaces
1435
1436--{
1437-- Topo-Geo and Topo-Net 3: Routine Details
1438-- X.3.17
1439--
1440--  ST_InitTopoGeo(atopology)
1441--
1442CREATE OR REPLACE FUNCTION topology.ST_InitTopoGeo(varchar)
1443RETURNS text
1444AS '
1445DECLARE
1446        atopology alias for $1;
1447        rec RECORD;
1448        topology_id numeric;
1449BEGIN
1450        IF atopology IS NULL THEN
1451                RAISE EXCEPTION ''SQL/MM Spatial exception - null argument'';
1452        END IF;
1453
1454        FOR rec IN SELECT * FROM pg_namespace WHERE text(nspname) = atopology
1455        LOOP
1456                RAISE EXCEPTION ''SQL/MM Spatial exception - schema already exists'';
1457        END LOOP;
1458
1459        FOR rec IN EXECUTE ''SELECT topology.CreateTopology(''
1460                ||quote_literal(atopology)|| '') as id''
1461        LOOP
1462                topology_id := rec.id;
1463        END LOOP;
1464
1465        RETURN ''Topology-Geometry '' || quote_literal(atopology)
1466                || '' (id:'' || topology_id || '') created. '';
1467END
1468'
1469LANGUAGE 'plpgsql' VOLATILE;
1470--} ST_InitTopoGeo
1471
1472--{
1473-- Topo-Geo and Topo-Net 3: Routine Details
1474-- X.3.18
1475--
1476--  ST_CreateTopoGeo(atopology, acollection)
1477--
1478CREATE OR REPLACE FUNCTION topology.ST_CreateTopoGeo(varchar, geometry)
1479RETURNS text
1480AS '
1481DECLARE
1482        atopology alias for $1;
1483        acollection alias for $2;
1484        typ char(4);
1485        rec RECORD;
1486        ret int;
1487        schemaoid oid;
1488BEGIN
1489        IF atopology IS NULL OR acollection IS NULL THEN
1490                RAISE EXCEPTION ''SQL/MM Spatial exception - null argument'';
1491        END IF;
1492
1493        -- Verify existance of the topology schema
1494        FOR rec in EXECUTE ''SELECT oid FROM pg_namespace WHERE ''
1495                || '' nspname = '' || quote_literal(atopology)
1496                || '' GROUP BY oid''
1497               
1498        LOOP
1499                schemaoid := rec.oid;
1500        END LOOP;
1501
1502        IF schemaoid IS NULL THEN
1503        RAISE EXCEPTION ''SQL/MM Spatial exception - non-existent schema'';
1504        END IF;
1505
1506        -- Verify existance of the topology views in the topology schema
1507        FOR rec in EXECUTE ''SELECT count(*) FROM pg_class WHERE ''
1508                || '' relnamespace = '' || schemaoid
1509                || '' and relname = ''''node''''''
1510                || '' OR relname = ''''edge''''''
1511                || '' OR relname = ''''face''''''
1512        LOOP
1513                IF rec.count < 3 THEN
1514        RAISE EXCEPTION ''SQL/MM Spatial exception - non-existent view'';
1515                END IF;
1516        END LOOP;
1517
1518        -- Verify the topology views in the topology schema to be empty
1519        FOR rec in EXECUTE
1520                ''SELECT count(*) FROM ''
1521                || quote_ident(atopology) || ''.edge_data ''
1522                || '' UNION '' ||
1523                ''SELECT count(*) FROM ''
1524                || quote_ident(atopology) || ''.node ''
1525        LOOP
1526                IF rec.count > 0 THEN
1527        RAISE EXCEPTION ''SQL/MM Spatial exception - non-empty view'';
1528                END IF;
1529        END LOOP;
1530
1531        -- face check is separated as it will contain a single (world)
1532        -- face record
1533        FOR rec in EXECUTE
1534                ''SELECT count(*) FROM ''
1535                || quote_ident(atopology) || ''.face ''
1536        LOOP
1537                IF rec.count != 1 THEN
1538        RAISE EXCEPTION ''SQL/MM Spatial exception - non-empty face view'';
1539                END IF;
1540        END LOOP;
1541
1542        --
1543        -- LOOP through the elements invoking the specific function
1544        --
1545        FOR rec IN SELECT geom(dump(acollection))
1546        LOOP
1547                typ := substring(geometrytype(rec.geom), 1, 3);
1548
1549                IF typ = ''LIN'' THEN
1550        SELECT topology.TopoGeo_addLinestring(atopology, rec.geom) INTO ret;
1551                ELSIF typ = ''POI'' THEN
1552        SELECT topology.TopoGeo_AddPoint(atopology, rec.geom) INTO ret;
1553                ELSIF typ = ''POL'' THEN
1554        SELECT topology.TopoGeo_AddPolygon(atopology, rec.geom) INTO ret;
1555                ELSE
1556        RAISE EXCEPTION ''ST_CreateTopoGeo got unknown geometry type: %'', typ;
1557                END IF;
1558
1559        END LOOP;
1560
1561        RETURN ''Topology '' || atopology || '' populated'';
1562
1563        RAISE EXCEPTION ''ST_CreateTopoGeo not implemente yet'';
1564END
1565'
1566LANGUAGE 'plpgsql' VOLATILE;
1567--} ST_CreateTopoGeo
1568
1569--=}  SQL/MM block
1570
Note: See TracBrowser for help on using the repository browser.