source: trunk/data/konvert/postnas_0.7/alkis-functions.sql @ 190

Revision 190, 17.6 KB checked in by j.e.fischer, 8 years ago (diff)

Allgemeinde Änderungen (Schemaänderungen gesondert im Anschluß):

2012-06-24

Festen Pfad zu PostNAS entfernt: ordner_konvertieren.sh,
datenbank_anlegen.sh, konv_batch.sh, konvertierung_kommandos_beispiele.txt

alkis-trigger-hist.sql und alkis-trigger-kill.sql:

ergänzt (setzt den jeweiligen delete-Trigger)

alkis-trigger.sql in svn:ignore aufgenommen


datenbank_anlegen.sh:

Ggf. Symlink alkis-trigger.sql auf alkis-trigger-kill.sql anlegen

konv_batch.sh:

  • GDAL in PATH aufgenommen und ogr2ogr in ohne Pfad aufgerufen
  • Löschen der historischen Daten wird ausgeführt, wenn Symlink auf alkis-trigger-kill.sql zeigt.

alkis-functions.sql:

Stored Procedures aus alkis_PostNAS_0.7_schema.sql ausgelagert

CRLF => LF:

pp_laden.sql, ordner_konvertieren.sh, datenbank_anlegen.sh, konv_batch.sh

Schemaanpassungen:

2012-12-03

ap_darstellung.advstandardmodell: varchar => varchar[]

2012-11-21

ax_besonderegebaeudelinie kann LINESTRING oder MULTILINESTRING sein (=>GEOMETRY)

2012-11-20

Koordinatensystem konfigurierbar anlegen (Variable :alkis_epsg)

2012-11-20

  • Ausführende Stellen ergänzt
    • Felder zu ax_historischesflurstueckalb ergänzt:
    • buchungsblattnummermitbuchstabenerweiterung/laufendenummerderbuchungsstelle zu Array
    • laufendenummerderfortfuehrung/fortfuehrungsart ergänzt
    • Indizes gesetzt
  • Felder zu ax_historischesflurstueck ergänzt:
    • buchungsblattnummermitbuchstabenerweiterung/buchungsblattkennzeichen zu Array
  • Feld relativehoehe zu ax_grenzpunkt / ax_aufnahmepunkt / ax_sicherungspunkt /
  • Tabelle ax_sonstigervermessungspunkt ergänzt
  • Koordinatenstatus zu ax_punktortag / ax_punktortau / ax_punktortta ergänzt
  • Felder zu ax_anschrift ergänzt: postleitzahlpostfach / postfach / ortsteil / weitereAdressen
  • Feld objekthoehe zu ax_bauwerkoderanlagefuerindustrieundgewerbe ergänzt
  • Feld sonstigeeigenschaft (Array) zu ax_besondererbauwerkspunkt ergänzt
  • Feld gemeindeflaeche zu ax_kommunalesgebiet hinzugefügt
  • Triggerausgabe korrigiert


2012-10-17

identifier bei ax_boeschungkliff und ax_boeschungsflaeche ergänzt

2012-09-09

  • ax_flurstueck/ax_historischesflurstueckalb/ax_historischesflurstueck
    • rechtsbehelfsverfahren / zweifelhafterFlurstuecksnachweis: integer => varchar default 'false'
  • ax_punktortag/ax_punktortau/ax_punktortta.kartendarstellung: integer => varchar
  • Neue Indizes:
    • auf endet in ap_ppo, ap_lpo, ap_darstellung, ap_pto, ax_punktortta,
    • ax_flurstueck auf:
      • land,gemarkungsnummer,flurnummer,zaehler,nenner
      • abweichenderrechtszustand
    • ax_buchungsblatt(land,bezirk,buchungsblattnummermitbuchstabenerweiterung)
    • ax_grenzpunkt(abmarkung_marke)
    • ap_pto(sn)
  • Indizes auf alkis_beziehungen / ax_historischesflurstueckalb / ax_grenzpunkt_abmm auf USING btree geändert
  • ap_lpo / ax_gebaeudeausgestaltung kann LINESTRING und MULTILINESTRING enthalten (=>GEOMETRY)

2012-06-24

  • Stored Procedures in alkis-funktions.sql ausgelagert
  • alkis_drop() aus Schema wird aufgerufen
  • Löschtrigger wird durch \i alkis-trigger.sql gesetzt (Symlink auf alkis-trigger-kill.sql oder alkis-trigger-hist.sql konfiguriert die Fortführungsoption)
  • Angleichung von ax_sicherungspunkt.beginnt, .identifier und .endet
  • Angleichung von ax_punktkennunguntergegangen.beginnt, .identifier und .endet
  • ax_vertretung und ax_verwaltungsgemeinschaft ergänzt
  • ax_besonderertopographischerpunkt.sonstigeeigenschaft varchar[] ergänzt
  • ax_grenzpunkt.besonderepunktnummer ergänzt
  • ax_gebaeude.weiteregebaeudefunktion => integer[]
  • ax_bauteil.dachform & anzahlderoberirdischengeschosse ergänzt
  • ax_besonderegebaeudelinie.beschaffenheit => integer[]
  • ap_lto.signaturnummer ergänzt
  • ax_gebaeude.name => name[]
  • ax_turm.zustand und name ergänzt
  • ax_bauwerkoderanlagefuerindustrieundgewerbe.name und zustand ergänzt
  • ax_vorratsbehaelterspeicherbauwerk.lagezurerdoberflaeche und name ergänzt
  • ax_transportanlage.produkt ergänzt
  • ax_bauwerkoderanlagefuersportfreizeitunderholung.name und sportart ergänzt
  • ax_historischesbauwerkoderhistorischeeinrichtung.name ergänzt
  • ax_einrichtunginoeffentlichenbereichen.kilometerangaben ergänzt
  • ax_bauwerkimverkehrsbereich.name und zustand ergänzt
  • ax_strassenverkehrsanlage.bezeichnung und name ergänzt
  • ax_wegpfadsteig.name ergänzt
  • ax_bahnverkehrsanlage.name ergänzt
  • ax_gleis.art, lagezuroberflaeche und name ergänzt
  • ax_bauwerkimgewaesserbereich.name und zustand ergänzt
  • ax_vegetationsmerkmal.zustand und name ergänzt
  • ax_gewaessermerkmal.name ergänzt
  • ax_untergeordnetesgewaesser.lagezurerdoberflaeche, name und hydrologischesmerkmal ergänzt
  • ap_darstellung.positionierungsregel ergänzt
  • ax_bodenschaetzung.sonstigeAngaben integer => integer[]
  • ax_grablochderbodenschaetzung.bedeutung integer => integer[]
  • ax_dammwalldeich.name ergänzt
  • ax_naturumweltoderbodenschutzrecht.name ergänzt
  • ax_gelaendekante.art ergänzt
  • ax_bauteil.advstandardmodel varchar => varchar[]
  • ax_gemarkung.advstandardmodel varchar => varchar[]
  • ax_buchungsstelle.advstandardmodel.zaehler/nenner => double precision
  • signaturnummer: integer => varchar
  • anlass: integer => varchar
  • ax_historischesflurstueckalb.buchungsblattkennzeichen: double precision => varchar
  • ax_verwaltung ergänzt
  • ax_kommunalesgebiet.schluesselgesamt: integer => varchar
Line 
1-- Table/View/Sequence löschen, wenn vorhanden
2CREATE OR REPLACE FUNCTION alkis_dropobject(t TEXT) RETURNS varchar AS $$
3DECLARE
4        c RECORD;
5        s varchar;
6        r varchar;
7        d varchar;
8        i integer;
9        tn varchar;
10BEGIN
11        r := '';
12        d := '';
13
14        -- drop objects
15        FOR c IN SELECT relkind,relname
16                FROM pg_class
17                JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
18                WHERE pg_namespace.nspname='public' AND pg_class.relname=t
19                ORDER BY relkind
20        LOOP
21                IF c.relkind = 'v' THEN
22                        r := r || d || 'Sicht ' || c.relname || ' gelöscht.';
23                        EXECUTE 'DROP VIEW ' || c.relname || ' CASCADE';
24                ELSIF c.relkind = 'r' THEN
25                        r := r || d || 'Tabelle ' || c.relname || ' gelöscht.';
26                        EXECUTE 'DROP TABLE ' || c.relname || ' CASCADE';
27                ELSIF c.relkind = 'S' THEN
28                        r := r || d || 'Sequenz ' || c.relname || ' gelöscht.';
29                        EXECUTE 'DROP SEQUENCE ' || c.relname;
30                ELSIF c.relkind <> 'i' THEN
31                        r := r || d || 'Typ ' || c.table_type || '.' || c.table_name || ' unerwartet.';
32                END IF;
33                d := E'\n';
34        END LOOP;
35
36        FOR c IN SELECT indexname FROM pg_indexes WHERE schemaname='public' AND indexname=t
37        LOOP
38                r := r || d || 'Index ' || c.indexname || ' gelöscht.';
39                EXECUTE 'DROP INDEX ' || c.indexname;
40                d := E'\n';
41        END LOOP;
42
43        FOR c IN SELECT proname,proargtypes
44                FROM pg_proc
45                JOIN pg_namespace ON pg_proc.pronamespace=pg_namespace.oid
46                WHERE pg_namespace.nspname='public' AND pg_proc.proname=t
47        LOOP
48                r := r || d || 'Funktion ' || c.proname || ' gelöscht.';
49
50                s := 'DROP FUNCTION ' || c.proname || '(';
51                d := '';
52
53                FOR i IN array_lower(c.proargtypes,1)..array_upper(c.proargtypes,1) LOOP
54                        SELECT typname INTO tn FROM pg_type WHERE oid=c.proargtypes[i];
55                        s := s || d || tn;
56                        d := ',';
57                END LOOP;
58
59                s := s || ')';
60
61                EXECUTE s;
62
63                d := E'\n';
64        END LOOP;
65
66        FOR c IN SELECT relname,conname
67                FROM pg_constraint
68                JOIN pg_class ON pg_constraint.conrelid=pg_constraint.oid
69                JOIN pg_namespace ON pg_constraint.connamespace=pg_namespace.oid
70                WHERE pg_namespace.nspname='public' AND pg_constraint.conname=t
71        LOOP
72                r := r || d || 'Constraint ' || c.conname || ' von ' || c.relname || ' gelöscht.';
73                EXECUTE 'ALTER TABLE ' || c.relname || ' DROP CONSTRAINT ' || c.conname;
74                d := E'\n';
75        END LOOP;
76
77        RETURN r;
78END;
79$$ LANGUAGE plpgsql;
80
81-- Alle ALKIS-Tabellen löschen
82SELECT alkis_dropobject('alkis_drop');
83CREATE FUNCTION alkis_drop() RETURNS varchar AS $$
84DECLARE
85        c RECORD;
86        r VARCHAR;
87        d VARCHAR;
88BEGIN
89        r := '';
90        d := '';
91        -- drop tables & views
92        FOR c IN SELECT table_type,table_name FROM information_schema.tables WHERE table_schema='public' AND ( substr(table_name,1,3) IN ('ax_','ap_','ks_') OR table_name IN ('alkis_beziehungen','delete')) ORDER BY table_type DESC LOOP
93                IF c.table_type = 'VIEW' THEN
94                        r := r || d || 'Sicht ' || c.table_name || ' gelöscht.';
95                        EXECUTE 'DROP VIEW ' || c.table_name || ' CASCADE';
96                ELSIF c.table_type = 'BASE TABLE' THEN
97                        r := r || d || 'Tabelle ' || c.table_name || ' gelöscht.';
98                        EXECUTE 'DROP TABLE ' || c.table_name || ' CASCADE';
99                ELSE
100                        r := r || d || 'Typ ' || c.table_type || '.' || c.table_name || ' unerwartet.';
101                END IF;
102                d := E'\n';
103        END LOOP;
104
105        -- clean geometry_columns
106        DELETE FROM geometry_columns
107                WHERE f_table_schema='public'
108                AND ( substr(f_table_name,1,2) IN ('ax_','ap_','ks_')
109                 OR f_table_name IN ('alkis_beziehungen','delete') );
110END;
111$$ LANGUAGE plpgsql;
112
113-- Table/View/Sequence löschen, wenn vorhanden
114CREATE OR REPLACE FUNCTION alkis_dropobject(t TEXT) RETURNS void AS $$
115DECLARE
116        c RECORD;
117BEGIN
118        -- drop objects
119        FOR c IN SELECT relkind,relname
120                FROM pg_class
121                JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
122                WHERE pg_namespace.nspname='public' AND pg_class.relname=t
123                ORDER BY relkind
124        LOOP
125                IF c.relkind = 'v' THEN
126                        RAISE NOTICE 'Dropping view %', c.relname;
127                        EXECUTE 'DROP VIEW ' || c.relname || ' CASCADE';
128                ELSIF c.relkind = 'r' THEN
129                        RAISE NOTICE 'Dropping table %', c.relname;
130                        EXECUTE 'DROP TABLE ' || c.relname || ' CASCADE';
131                ELSIF c.relkind = 'S' THEN
132                        RAISE NOTICE 'Dropping sequence %', c.relname;
133                        EXECUTE 'DROP SEQUENCE ' || c.relname;
134                ELSIF c.relkind <> 'i' THEN
135                        RAISE NOTICE 'Unexpected type %,%', c.relkind, c.relname;
136                END IF;
137        END LOOP;
138END;
139$$ LANGUAGE plpgsql;
140
141-- Alle ALKIS-Tabellen leeren
142SELECT alkis_dropobject('alkis_delete');
143CREATE FUNCTION alkis_delete() RETURNS varchar AS $$
144DECLARE
145        c RECORD;
146        r varchar;
147        d varchar;
148BEGIN
149        r := '';
150        d := '';
151
152        -- drop views
153        FOR c IN
154                SELECT table_name
155                FROM information_schema.tables
156                WHERE table_schema='public' AND table_type='BASE TABLE'
157                  AND ( substr(table_name,1,3) IN ('ax_','ap_','ks_')
158                        OR table_name IN ('alkis_beziehungen','delete') )
159        LOOP
160                r := r || d || c.table_name || ' wurde geleert.';
161                EXECUTE 'DELETE FROM '||c.table_name;
162                d := E'\n';
163        END LOOP;
164
165        RETURN r;
166END;
167$$ LANGUAGE plpgsql;
168
169-- Übersicht erzeugen, die alle alkis_beziehungen mit den Typen der beteiligen ALKIS-Objekte versieht
170SELECT alkis_dropobject('alkis_mviews');
171CREATE FUNCTION alkis_mviews() RETURNS varchar AS $$
172DECLARE
173        sql TEXT;
174        delim TEXT;
175        c RECORD;
176BEGIN
177        SELECT alkis_dropobject('vbeziehungen') INTO sql;
178        SELECT alkis_dropobject('vobjekte') INTO sql;
179
180        delim := '';
181        sql := 'CREATE VIEW vobjekte AS ';
182
183        FOR c IN SELECT table_name FROM information_schema.columns WHERE column_name='gml_id' AND substr(table_name,1,3) IN ('ax_','ap_','ks_') LOOP
184                sql := sql || delim || 'SELECT gml_id,beginnt,''' || c.table_name || ''' AS table_name FROM ' || c.table_name;
185                delim := ' UNION ';
186        END LOOP;
187
188        EXECUTE sql;
189
190--      CREATE UNIQUE INDEX vobjekte_gmlid ON vobjekte(gml_id,beginnt);
191--      CREATE INDEX vobjekte_table ON vobjekte(table_name);
192
193        CREATE VIEW vbeziehungen AS
194                SELECT  beziehung_von,(SELECT table_name FROM vobjekte WHERE gml_id=beziehung_von) AS typ_von
195                        ,beziehungsart
196                        ,beziehung_zu,(SELECT table_name FROM vobjekte WHERE gml_id=beziehung_zu) AS typ_zu
197                FROM alkis_beziehungen;
198
199--      CREATE INDEX vbeziehungen_von    ON vbeziehungen(beziehung_von);
200--      CREATE INDEX vbeziehungen_vontyp ON vbeziehungen(typ_von);
201--      CREATE INDEX vbeziehungen_art    ON vbeziehungen(beziehungsart);
202--      CREATE INDEX vbeziehungen_zu     ON vbeziehungen(beziehung_zu);
203--      CREATE INDEX vbeziehungen_zutyp  ON vbeziehungen(typ_zu);
204
205        RETURN 'ALKIS-Views erzeugt.';
206END;
207$$ LANGUAGE plpgsql;
208
209-- Indizes erzeugen
210SELECT alkis_dropobject('alkis_update_schema');
211CREATE FUNCTION alkis_update_schema() RETURNS varchar AS $$
212DECLARE
213        sql TEXT;
214        c RECORD;
215        i RECORD;
216        n INTEGER;
217BEGIN
218        -- Spalten in delete ergÀnzen
219        SELECT count(*) INTO n FROM information_schema.columns WHERE table_schema='public' AND table_name='delete' AND column_name='ignored';
220        IF n=0 THEN
221                ALTER TABLE "delete" ADD ignored BOOLEAN;
222        END IF;
223
224        SELECT count(*) INTO n FROM information_schema.columns WHERE table_schema='public' AND table_name='delete' AND column_name='context';
225        IF n=0 THEN
226                ALTER TABLE "delete" ADD context VARCHAR;
227        END IF;
228
229        SELECT count(*) INTO n FROM information_schema.columns WHERE table_schema='public' AND table_name='delete' AND column_name='safetoignore';
230        IF n=0 THEN
231                ALTER TABLE "delete" ADD safetoignore VARCHAR;
232        END IF;
233
234        SELECT count(*) INTO n FROM information_schema.columns WHERE table_schema='public' AND table_name='delete' AND column_name='replacedby';
235        IF n=0 THEN
236                ALTER TABLE "delete" ADD replacedBy VARCHAR;
237        END IF;
238
239        -- Spalte identifier ergÀnzen, wo sie fehlt
240        FOR c IN SELECT table_name FROM information_schema.columns a WHERE a.column_name='gml_id'
241                AND     EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='beginnt'    AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
242                AND NOT EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='identifier' AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
243        LOOP
244                EXECUTE 'ALTER TABLE ' || c.table_name || ' ADD identifier character(44)';
245        END LOOP;
246
247        -- Spalte endet ergÀnzen, wo sie fehlt
248        FOR c IN SELECT table_name FROM information_schema.columns a WHERE a.column_name='gml_id'
249                AND     EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='beginnt' AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
250                AND NOT EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='endet'   AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
251        LOOP
252                EXECUTE 'ALTER TABLE ' || c.table_name || ' ADD endet character(20) CHECK (endet>beginnt)';
253        END LOOP;
254
255        -- Lebensdauer-Constraint ergÀnzen
256        FOR c IN SELECT table_name FROM information_schema.columns a WHERE a.column_name='gml_id'
257                AND EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='beginnt' AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
258                AND EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='endet'   AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
259        LOOP
260                SELECT alkis_dropobject(c.table_name||'_lebensdauer');
261                EXECUTE 'ALTER TABLE ' || c.table_name || ' ADD CONSTRAINT ' || c.table_name || '_lebensdauer CHECK (beginnt IS NOT NULL AND endet>beginnt)';
262        END LOOP;
263
264        -- Indizes aktualisieren
265        FOR c IN SELECT table_name FROM information_schema.columns a WHERE a.column_name='gml_id'
266                AND EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='beginnt' AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
267        LOOP
268                -- Vorhandene Indizes droppen (TODO: Löscht auch die SonderfÀlle - entfernen)
269                FOR i IN EXECUTE 'SELECT indexname FROM pg_indexes WHERE NOT indexname LIKE ''%_pk'' AND schemaname=''public'' AND tablename='''||c.table_name||'''' LOOP
270                        EXECUTE 'DROP INDEX ' || i.indexname;
271                END LOOP;
272
273                -- Indizes erzeugen
274                EXECUTE 'CREATE UNIQUE INDEX ' || c.table_name || '_id ON ' || c.table_name || '(gml_id,beginnt)';
275                EXECUTE 'CREATE UNIQUE INDEX ' || c.table_name || '_ident ON ' || c.table_name || '(identifier)';
276                EXECUTE 'CREATE INDEX ' || c.table_name || '_gmlid ON ' || c.table_name || '(gml_id)';
277                EXECUTE 'CREATE INDEX ' || c.table_name || '_beginnt ON ' || c.table_name || '(beginnt)';
278                EXECUTE 'CREATE INDEX ' || c.table_name || '_endet ON ' || c.table_name || '(endet)';
279        END LOOP;
280
281        -- Geometrieindizes aktualisieren
282        FOR c IN SELECT table_name FROM information_schema.columns a WHERE a.column_name='gml_id'
283                AND EXISTS (SELECT * FROM information_schema.columns b WHERE b.column_name='wkb_geometry' AND a.table_catalog=b.table_catalog AND a.table_schema=b.table_schema AND a.table_name=b.table_name)
284        LOOP
285                EXECUTE 'CREATE INDEX ' || c.table_name || '_geom ON ' || c.table_name || ' USING GIST (wkb_geometry)';
286        END LOOP;
287
288        RETURN 'Schema aktualisiert.';
289END;
290$$ LANGUAGE plpgsql;
291
292
293-- Löschsatz verarbeiten (MIT Historie)
294-- context='delete'        => "endet" auf aktuelle Zeit setzen
295-- context='replace'       => "endet" des ersetzten auf "beginnt" des neuen Objekts setzen
296CREATE OR REPLACE FUNCTION delete_feature_hist() RETURNS TRIGGER AS $$
297DECLARE
298        sql TEXT;
299        gml_id TEXT;
300        endete TEXT;
301        n INTEGER;
302BEGIN
303        NEW.context := lower(NEW.context);
304        gml_id      := substr(NEW.featureid, 1, 16);
305
306        IF NEW.context IS NULL THEN
307                NEW.context := 'delete';
308        END IF;
309
310        IF NEW.context='delete' THEN
311                endete := to_char(CURRENT_TIMESTAMP AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"');
312
313        ELSIF NEW.context='replace' THEN
314                NEW.safetoignore := lower(NEW.safetoignore);
315
316                IF NEW.safetoignore IS NULL THEN
317                        RAISE EXCEPTION '%: safeToIgnore nicht gesetzt.', NEW.featureid;
318                ELSIF NEW.safetoignore<>'true' AND NEW.safetoignore<>'false' THEN
319                        RAISE EXCEPTION '%: safeToIgnore ''%'' ungÃŒltig (''true'' oder ''false'' erwartet).', NEW.featureid, NEW.safetoignore;
320                END IF;
321
322                IF NEW.replacedBy IS NULL OR NEW.replacedBy = '' THEN
323                        IF NEW.safetoignore = 'true' THEN
324                                RAISE NOTICE '%: Nachfolger nicht gesetzt - ignoriert', NEW.featureid;
325                                NEW.ignored := true;
326                                RETURN NEW;
327                        ELSE
328                                RAISE EXCEPTION '%: Nachfolger nicht gesetzt', NEW.featureid;
329                        END IF;
330                END IF;
331
332                sql := 'SELECT beginnt FROM ' || NEW.typename || ' WHERE identifier=''urn:adv:oid:' || NEW.replacedBy || '''';
333                -- RAISE NOTICE 'SQL: %', sql;
334
335                -- FEHLER: identifier enthÀlt nur gml_id, aber nicht den Timestamp dahinter
336                --         Daher wird das zu ersetzende Objekt nicht gefunden
337
338                EXECUTE sql INTO endete;
339
340                IF endete IS NULL AND length(NEW.replacedBy)>16 THEN
341                        RAISE NOTICE '%: Nachfolger % nicht gefunden - versuche ''%''', NEW.featureid, NEW.replacedBy, substr(NEW.replacedBy, 1, 16);
342                        sql := 'SELECT beginnt FROM ' || NEW.typename
343                            || ' WHERE gml_id=''' || substr(NEW.replacedBy, 1, 16) || ''''
344                            || ' AND endet IS NULL'
345                            || ' AND identifier<>''urn:adv:oid:'|| NEW.featureid || ''''
346                            || ' ORDER BY beginnt DESC'
347                            || ' LIMIT 1';
348                        EXECUTE sql INTO endete;
349                        gml_id := gml_id || ''' AND beginnt<>''' || endete;
350                END IF;
351
352                IF endete IS NULL THEN
353                        IF NEW.safetoignore = 'true' THEN
354                                RAISE NOTICE '%: Nachfolger % nicht gefunden - ignoriert', NEW.featureid, NEW.replacedBy;
355                                NEW.ignored := true;
356                                RETURN NEW;
357                        ELSE
358                                RAISE EXCEPTION '%: Nachfolger % nicht gefunden', NEW.featureid, NEW.replacedBy;
359                        END IF;
360                END IF;
361
362                -- RAISE NOTICE '%: Nachfolgeobjekt beginnt um %.', NEW.featureid, endete;
363        ELSE
364                RAISE EXCEPTION '%: UngÃŒltiger Kontext % (''delete'' oder ''replace'' erwartet).', NEW.featureid, NEW.context;
365        END IF;
366
367        sql     := 'UPDATE ' || NEW.typename
368                || ' SET endet=''' || endete || ''''
369                || ' WHERE (identifier=''urn:adv:oid:' || NEW.featureid || ''' OR identifier=''urn:adv:oid:' || gml_id || ''')'
370                || ' AND endet IS NULL';
371        -- RAISE NOTICE 'SQL: %', sql;
372        EXECUTE sql;
373        GET DIAGNOSTICS n = ROW_COUNT;
374        IF n<>1 THEN
375                RAISE NOTICE 'SQL: %', sql;
376                IF NEW.context = 'delete' OR NEW.safetoignore = 'true' THEN
377                        RAISE NOTICE '%: Untergangsdatum von % Objekten statt nur einem auf % gesetzt - ignoriert', NEW.featureid, n, endete;
378                        NEW.ignored := true;
379                        RETURN NEW;
380                ELSE
381                        RAISE EXCEPTION '%: Untergangsdatum von % Objekten statt nur einem auf % gesetzt - ignoriert', NEW.featureid, n, endete;
382                END IF;
383        END IF;
384
385        NEW.ignored := false;
386        RETURN NEW;
387END;
388$$ LANGUAGE plpgsql;
389
390
391-- Löschsatz verarbeiten (OHNE Historie)
392-- historische Objekte werden sofort gelöscht.
393-- Siehe Mail W. Jacobs vom 23.03.2012 in PostNAS-Mailingliste
394-- geaendert krz FJ 2012-10-31
395CREATE OR REPLACE FUNCTION delete_feature_kill() RETURNS TRIGGER AS $$
396DECLARE
397        query TEXT;
398        begsql TEXT;
399        aktbeg TEXT;
400        gml_id TEXT;
401BEGIN
402        NEW.typename := lower(NEW.typename);
403        NEW.context := lower(NEW.context);
404        gml_id      := substr(NEW.featureid, 1, 16);
405
406        IF NEW.context IS NULL THEN
407                NEW.context := 'delete';
408        END IF;
409
410        IF NEW.context='delete' THEN
411                -- ersatzloses Loeschen eines Objektes
412
413                query := 'DELETE FROM ' || NEW.typename
414                        || ' WHERE gml_id = ''' || gml_id || '''';
415                EXECUTE query;
416
417                query := 'DELETE FROM alkis_beziehungen WHERE beziehung_von = ''' || gml_id
418                        || ''' OR beziehung_zu = ''' || gml_id || '''';
419                EXECUTE query;
420                RAISE NOTICE 'Lösche gml_id % in % und Beziehungen', gml_id, NEW.typename;
421
422        ELSE
423                -- Ersetzen eines Objektes
424                -- In der objekt-Tabelle sind bereits 2 Objekte vorhanden (alt und neu).
425                -- Die 2 DatensÀtze unterscheiden sich nur in ogc_fid und beginnt
426
427                -- beginnt-Wert des aktuellen Objektes ermitteln
428                -- RAISE NOTICE 'Suche beginnt von neuem gml_id % ', substr(NEW.replacedBy, 1, 16);
429                begsql := 'SELECT max(beginnt) FROM ' || NEW.typename || ' WHERE gml_id = ''' || substr(NEW.replacedBy, 1, 16) || ''' AND endet IS NULL';
430                EXECUTE begsql INTO aktbeg;
431
432                -- Nur alte Objekte entfernen
433                query := 'DELETE FROM ' || NEW.typename
434                        || ' WHERE gml_id = ''' || gml_id || ''' AND beginnt < ''' || aktbeg || '''';
435                EXECUTE query;
436
437                -- Tabelle alkis_beziehungen
438                IF gml_id = substr(NEW.replacedBy, 1, 16) THEN -- gml_id gleich
439                        -- Beziehungen des Objektes wurden redundant noch einmal eingetragen
440                        -- ToDo:         HIER sofort die Redundanzen zum aktuellen Objekt beseitigen.
441                        -- Workaround: Nach der Konvertierung werden im Post-Processing
442                        --             ALLE Redundanzen mit einem SQL-Statemant beseitigt.
443                --      RAISE NOTICE 'Ersetze gleiche gml_id % in %', gml_id, NEW.typename;
444
445                -- ENTWURF ungetestet:
446                --query := 'DELETE FROM alkis_beziehungen AS bezalt
447                --      WHERE (bezalt.beziehung_von = ' || gml_id || ' OR bezalt.beziehung_zu = ' || gml_id ||')
448                --      AND EXISTS (SELECT ogc_fid FROM alkis_beziehungen AS bezneu
449                --              WHERE bezalt.beziehung_von = bezneu.beziehung_von
450                --              AND bezalt.beziehung_zu = bezneu.beziehung_zu
451                --              AND bezalt.beziehungsart = bezneu.beziehungsart
452                --              AND bezalt.ogc_fid < bezneu.ogc_fid);'
453                --EXECUTE query;
454
455                ELSE
456                        -- replace mit ungleicher gml_id
457                        -- Falls dies vorkommt, die Function erweitern
458                        RAISE EXCEPTION '%: neue gml_id % bei Replace in %. alkis_beziehungen muss aktualisiert werden!', gml_id, NEW.replacedBy, NEW.typename;
459                END IF;
460        END IF;
461
462        NEW.ignored := false;
463        RETURN NEW;
464END;
465$$ LANGUAGE plpgsql;
466
467-- Im Trigger 'delete_feature_trigger' muss eine dieser beiden Funktionen
468-- (delete_feature_hist oder delete_feature_kill) verlinkt werden, je nachdem ob nur
469-- aktuelle oder auch historische Objekte in der Datenbank gefÃŒhrt werden sollen.
470
471-- Wenn die Datenbank MIT Historie angelegt wurde, kann nach dem Laden hiermit aufgerÀumt werden.
472CREATE OR REPLACE FUNCTION alkis_delete_all_endet() RETURNS void AS $$
473DECLARE
474        c RECORD;
475BEGIN
476        -- In allen Tabellen die Objekte Löschen, die ein Ende-Datum haben
477        FOR c IN
478                SELECT table_name
479                FROM information_schema.columns a
480                WHERE a.column_name='endet'
481                ORDER BY table_name
482        LOOP
483                EXECUTE 'DELETE FROM ' || c.table_name || ' WHERE NOT endet IS NULL';
484                -- RAISE NOTICE 'Lösche ''endet'' in: %', c.table_name;
485        END LOOP;
486END;
487$$ LANGUAGE plpgsql;
Note: See TracBrowser for help on using the repository browser.