Mercurial > gemma
changeset 4956:7cc79c65a9e5 fairway-marks-import
Keep the history of fairway marks
ToDo: Set end to validity period when an entry can no longer be found
in a data source.
author | Tom Gottfried <tom@intevation.de> |
---|---|
date | Wed, 26 Feb 2020 12:18:15 +0100 |
parents | 5c43427fc2bf |
children | b0607611bcdf |
files | pkg/imports/fm.go pkg/imports/pointwfs.go schema/gemma.sql schema/updates/1405/01.add_fm_validity.sql schema/updates/1405/02.recreate_fm_indexes.sql |
diffstat | 5 files changed, 227 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/imports/fm.go Wed Feb 26 11:25:28 2020 +0100 +++ b/pkg/imports/fm.go Wed Feb 26 12:18:15 2020 +0100 @@ -324,11 +324,41 @@ const ( // Format string to be completed with type and additional attributes + /* Instead of the row comparisons in the WHERE clauses + of the CTE with the UPDATE and the INSERT ... SELECT, we could have + used the row-based UNIQUE indexes as arbiter indexes + in an INSERT ... ON CONFLICT ... DO UPDATE, but that turned out + to be able to bypass the UNIQUE index in some cases. + */ insertFMSQLtmpl = ` WITH a AS ( SELECT users.current_user_area_utm() AS a +), +g AS ( + SELECT newfm + FROM ST_Transform(ST_GeomFromWKB($1, $2::integer), 4326) AS newfm (newfm) + WHERE pg_has_role('sys_admin', 'MEMBER') + OR ST_Intersects((select a from a), + ST_Transform(newfm, (select ST_SRID(a) from a))) +), +t AS ( + -- Currently valid and otherwise identical entry's validity. + /* If there are no intermittent updates of validity, + there will always be only one currently valid and + otherwise identical entry. */ + UPDATE waterway.fairway_marks_%[1]s SET last_found = current_timestamp + WHERE validity @> current_timestamp + AND (geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + %[2]s + ) IS NOT DISTINCT FROM ( + (SELECT newfm FROM g), + $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, + %[3]s) + RETURNING validity ) -INSERT INTO waterway.fairway_marks_%s ( +INSERT INTO waterway.fairway_marks_%[1]s ( geom, datsta, datend, @@ -343,25 +373,42 @@ txtdsc, sordat, sorind, - %s + %[2]s ) SELECT newfm, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, - %s - FROM ST_Transform(ST_GeomFromWKB($1, $2::integer), 4326) AS newfm (newfm) - WHERE pg_has_role('sys_admin', 'MEMBER') - OR ST_Intersects((select a from a), - ST_Transform(newfm, (select ST_SRID(a) from a))) -ON CONFLICT ( - CAST((geom, - datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, - scamin, picrep, txtdsc, sordat, sorind, - 0, %[2]s - ) AS waterway.fairway_marks_%[1]s) - ) - DO NOTHING + %[3]s + FROM g + WHERE NOT EXISTS(SELECT 1 FROM waterway.fairway_marks_%[1]s + WHERE ( + validity, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + %[2]s + ) IS NOT DISTINCT FROM ( + (SELECT validity FROM t), newfm, + $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, + %[3]s + ) + ) RETURNING id ` + // Assume validity ended for all entries not found in data source + // TODO: Apply this query after looping over all entries in data source + invalidateFairwayMarksSQLtmpl = ` +WITH + a AS ( + SELECT users.current_user_area_utm() AS a + ) +UPDATE waterway.fairway_marks_%s + SET validity = tstzrange(lower(validity), current_timestamp) + WHERE validity @> current_timestamp + AND last_found < current_timestamp + AND (pg_has_role('sys_admin', 'MEMBER') + OR ST_Intersects((select a from a), + ST_Transform(CAST(geom AS geometry), (select ST_SRID(a) from a)))) + ` + insertBcnlatDirimpSQL = ` INSERT INTO waterway.fairway_marks_bcnlat_dirimps (fm_bcnlat_id, dirimp) VALUES ($1, $2)
--- a/pkg/imports/pointwfs.go Wed Feb 26 11:25:28 2020 +0100 +++ b/pkg/imports/pointwfs.go Wed Feb 26 12:18:15 2020 +0100 @@ -206,7 +206,7 @@ if dupes > 0 { feedback.Info( - "Features outside responsibility area and duplicates: %d", + "Features outside responsibility area, duplicates or unchanged: %d", dupes) } @@ -222,15 +222,17 @@ feedback.Warn("Unsupported types found: %s", unsupported) } - if features == 0 { - return nil, UnchangedError("no valid new features found") - } - + // Commit before eventually returning UnchangedError because we might + // have updated last_found if err = consumer.Commit(); err == nil { feedback.Info("Storing %d features took %s", features, time.Since(start)) } + if features == 0 { + return nil, UnchangedError("no valid new features found") + } + return nil, nil }
--- a/schema/gemma.sql Wed Feb 26 11:25:28 2020 +0100 +++ b/schema/gemma.sql Wed Feb 26 12:18:15 2020 +0100 @@ -855,9 +855,13 @@ ) -- Attributes common to all fairway marks - -- according to IENC feature catalogue CREATE TABLE fairway_marks ( + validity tstzrange NOT NULL DEFAULT tstzrange(current_timestamp, NULL) + CHECK (NOT isempty(validity)), + -- Last time an import job found this entry in a data source: + last_found timestamp with time zone NOT NULL DEFAULT current_timestamp, geom geography(POINT, 4326) NOT NULL, + -- Attributes according to IENC Feature Catalogue: datsta varchar, datend varchar, persta varchar, @@ -886,7 +890,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_bcnlat_distinct_rows ON fairway_marks_bcnlat - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, condtn, bcnshp, catlam @@ -913,7 +917,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_boycar_distinct_rows ON fairway_marks_boycar - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, conrad, marsys, boyshp, catcam @@ -934,7 +938,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_boylat_distinct_rows ON fairway_marks_boylat - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, conrad, marsys, boyshp, catlam @@ -954,7 +958,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_boysaw_distinct_rows ON fairway_marks_boysaw - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, conrad, marsys, boyshp @@ -975,7 +979,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_boyspp_distinct_rows ON fairway_marks_boyspp - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, conrad, marsys, boyshp, catspm @@ -995,7 +999,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_daymar_distinct_rows ON fairway_marks_daymar - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, condtn, topshp, orient @@ -1030,7 +1034,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_lights_distinct_rows ON fairway_marks_lights - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, condtn, orient, catlit, exclit, litchr, litvis, @@ -1050,7 +1054,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_rtpbcn_distinct_rows ON fairway_marks_rtpbcn - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, condtn, siggrp, catrtb, radwal @@ -1069,7 +1073,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_topmar_distinct_rows ON fairway_marks_topmar - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, colour, colpat, condtn, topshp @@ -1096,7 +1100,7 @@ -- (i.e. considering two NULL values in a field equal): CREATE UNIQUE INDEX fairway_marks_notmrk_distinct_rows ON fairway_marks_notmrk - ((CAST((geom, + ((CAST((validity, last_found, geom, datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, scamin, picrep, txtdsc, sordat, sorind, 0, condtn, marsys, orient, status, addmrk, catnmk,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1405/01.add_fm_validity.sql Wed Feb 26 12:18:15 2020 +0100 @@ -0,0 +1,51 @@ +CREATE TABLE waterway.fairway_marks_new ( + validity tstzrange NOT NULL DEFAULT tstzrange(current_timestamp, NULL) + CHECK (NOT isempty(validity)), + last_found timestamp with time zone NOT NULL DEFAULT current_timestamp, + LIKE waterway.fairway_marks +); + +DO LANGUAGE plpgsql +$$ +DECLARE table_suffix varchar; +BEGIN + /* Re-write tables inheriting from fairway_marks to include new columns + in correct position */ + FOREACH table_suffix IN ARRAY ARRAY[ + 'bcnlat', 'boycar', 'boylat', 'boysaw', 'boyspp', + 'daymar', 'lights', 'rtpbcn', 'topmar', 'notmrk'] + LOOP + EXECUTE format('CREATE TABLE waterway.fairway_marks_%s_new ' + '(LIKE waterway.fairway_marks_%1$s INCLUDING ALL) ' + 'INHERITS (waterway.fairway_marks_new)', table_suffix); + /* Drop index referring to wrong columns. See + https://www.postgresql.org/message-id/flat/16272-6e32da020e9a9381%40postgresql.org + */ + EXECUTE format('DROP INDEX waterway.fairway_marks_%s_new_row_idx', + table_suffix); + EXECUTE format('INSERT INTO waterway.fairway_marks_%s_new ' + 'SELECT tstzrange(current_timestamp, NULL), current_timestamp, * ' + 'FROM waterway.fairway_marks_%1$s', table_suffix); + EXECUTE format('DROP TABLE waterway.fairway_marks_%s CASCADE', + table_suffix); + EXECUTE format('ALTER TABLE waterway.fairway_marks_%s_new ' + 'RENAME TO fairway_marks_%1$s', table_suffix); + END LOOP; + + /* Recreate foreign key constraints */ + FOREACH table_suffix IN ARRAY ARRAY['bcnlat', 'daymar', 'notmrk'] + LOOP + EXECUTE format('ALTER TABLE waterway.fairway_marks_%1$s_dirimps ' + 'ADD FOREIGN KEY (fm_%1$s_id) ' + 'REFERENCES waterway.fairway_marks_%1$s', table_suffix); + END LOOP; +END; +$$; + +DROP TABLE waterway.fairway_marks; +ALTER TABLE waterway.fairway_marks_new RENAME TO fairway_marks; + +-- Restore GRANTs +GRANT SELECT on ALL tables in schema waterway TO waterway_user ; +GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA waterway + TO waterway_admin;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1405/02.recreate_fm_indexes.sql Wed Feb 26 12:18:15 2020 +0100 @@ -0,0 +1,92 @@ +CREATE UNIQUE INDEX fairway_marks_bcnlat_distinct_rows + ON waterway.fairway_marks_bcnlat + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, bcnshp, catlam + ) AS waterway.fairway_marks_bcnlat) + )); + +CREATE UNIQUE INDEX fairway_marks_boycar_distinct_rows + ON waterway.fairway_marks_boycar + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp, catcam + ) AS waterway.fairway_marks_boycar) + )); + +CREATE UNIQUE INDEX fairway_marks_boylat_distinct_rows + ON waterway.fairway_marks_boylat + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp, catlam + ) AS waterway.fairway_marks_boylat) + )); + + +CREATE UNIQUE INDEX fairway_marks_boysaw_distinct_rows + ON waterway.fairway_marks_boysaw + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp + ) AS waterway.fairway_marks_boysaw) + )); + +CREATE UNIQUE INDEX fairway_marks_boyspp_distinct_rows + ON waterway.fairway_marks_boyspp + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp, catspm + ) AS waterway.fairway_marks_boyspp) + )); + +CREATE UNIQUE INDEX fairway_marks_daymar_distinct_rows + ON waterway.fairway_marks_daymar + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, topshp, orient + ) AS waterway.fairway_marks_daymar) + )); + +CREATE UNIQUE INDEX fairway_marks_lights_distinct_rows + ON waterway.fairway_marks_lights + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, condtn, orient, catlit, exclit, litchr, litvis, + mltylt, sectr1, sectr2, siggrp, sigper, sigseq, status + ) AS waterway.fairway_marks_lights) + )); + +CREATE UNIQUE INDEX fairway_marks_rtpbcn_distinct_rows + ON waterway.fairway_marks_rtpbcn + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, condtn, siggrp, catrtb, radwal + ) AS waterway.fairway_marks_rtpbcn) + )); + +CREATE UNIQUE INDEX fairway_marks_topmar_distinct_rows + ON waterway.fairway_marks_topmar + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, topshp + ) AS waterway.fairway_marks_topmar) + )); + +CREATE UNIQUE INDEX fairway_marks_notmrk_distinct_rows + ON waterway.fairway_marks_notmrk + ((CAST((validity, last_found, geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, condtn, marsys, orient, status, addmrk, catnmk, + disipd, disipu, disbk1, disbk2, fnctnm, bnkwtw + ) AS waterway.fairway_marks_notmrk) + ));