Mercurial > gemma
view schema/updates/1100/02.remove_bottleneck_validity_refs.sql @ 5560:f2204f91d286
Join the log lines of imports to the log exports to recover data from them.
Used in SR export to extract information that where in the meta json
but now are only found in the log.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 09 Feb 2022 18:34:40 +0100 |
parents | 30a567b1cc2e |
children |
line wrap: on
line source
-- This is Free Software under GNU Affero General Public License v >= 3.0 -- without warranty, see README.md and license for details. -- SPDX-License-Identifier: AGPL-3.0-or-later -- License-Filename: LICENSES/AGPL-3.0.txt -- Copyright (C) 2019 by via donau -- – Österreichische Wasserstraßen-Gesellschaft mbH -- Software engineering by Intevation GmbH -- Author(s): -- * Sascha Wilde <sascha.wilde@intevation.de> -- -- CONSTRAINT FUNCTIONS -- -- We still want to ensure, that there is at least a valid bottleneck -- at any time of the referencing objects validity. To ensure this we -- need a trigger constraint: CREATE OR REPLACE FUNCTION check_valid_bottleneck_ts() RETURNS trigger AS $$ DECLARE referenced_bottleneck_id text; new_tstz timestamptz; BEGIN EXECUTE format('SELECT $1.%I', TG_ARGV[0]) INTO referenced_bottleneck_id USING NEW; EXECUTE format('SELECT $1.%I', TG_ARGV[1]) INTO new_tstz USING NEW; IF EXISTS ( SELECT * FROM waterway.bottlenecks WHERE bottleneck_id = referenced_bottleneck_id AND validity @> new_tstz ) THEN RETURN NEW; ELSE RAISE EXCEPTION 'new row for relation "%" violates constraint trigger "%"', TG_TABLE_NAME, TG_NAME USING DETAIL = format('No matching bottleneck %s for %s found.', referenced_bottleneck_id, new_tstz), ERRCODE = 23505, SCHEMA = TG_TABLE_SCHEMA, TABLE = TG_TABLE_NAME, COLUMN = TG_ARGV[0], CONSTRAINT = TG_NAME; END IF; END; $$ LANGUAGE plpgsql; -- Redifine constraint trigger: sounding Results must intersect with -- the area of the bottleneck they belong to. Bottleneck is -- determined dynamically via date_info. CREATE OR REPLACE FUNCTION check_sr_in_bn_area() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF NOT st_intersects((SELECT area FROM waterway.bottlenecks WHERE bottleneck_id = NEW.bottleneck_id AND validity @> NEW.date_info::timestamptz), NEW.area) THEN RAISE EXCEPTION 'new row for relation "%" violates constraint trigger "%"', TG_TABLE_NAME, TG_NAME USING DETAIL = 'Failing row area has no intersection with bottleneck.', ERRCODE = 23514, SCHEMA = TG_TABLE_SCHEMA, TABLE = TG_TABLE_NAME, CONSTRAINT = TG_NAME; END IF; RETURN NEW; END; $$; -- -- SOUNDING RESULTS -- -- Dynamic version of sounding_differences geoserver view: Instead of -- a static reference to a specific bottleneck data set via primary -- key (id, validity) we check for a bottleneck valid at the time of -- the survey at executiuon time. CREATE OR REPLACE VIEW waterway.sounding_differences AS SELECT sd.id AS id, bn.objnam AS objnam, srm.date_info AS minuend, srs.date_info AS subtrahend, sdcl.height AS height, CAST(sdcl.lines AS geometry(multilinestring, 4326)) AS lines FROM caching.sounding_differences sd JOIN caching.sounding_differences_contour_lines sdcl ON sd.id = sdcl.sounding_differences_id JOIN waterway.sounding_results srm ON sd.minuend = srm.id JOIN waterway.sounding_results srs ON sd.subtrahend = srs.id JOIN waterway.bottlenecks bn ON srm.bottleneck_id = bn.bottleneck_id AND srm.date_info::timestamptz <@ bn.validity; -- As we resolve the correct gauge data to use on runtime, we drop the -- hard reference to the bottlenecks vaidity: ALTER TABLE waterway.sounding_results DROP IF EXISTS bottleneck_validity; -- Note, we now use prefixed names, to ensure correct execution order -- for the triggers... DROP TRIGGER IF EXISTS a_sounding_results_reference_bottleneck ON waterway.sounding_results; CREATE CONSTRAINT TRIGGER a_sounding_results_reference_bottleneck AFTER INSERT OR UPDATE OF bottleneck_id ON waterway.sounding_results FOR EACH ROW EXECUTE FUNCTION check_valid_bottleneck_ts('bottleneck_id','date_info'); DROP TRIGGER IF EXISTS sounding_results_in_bn_area ON waterway.sounding_results; DROP TRIGGER IF EXISTS b_sounding_results_in_bn_area ON waterway.sounding_results; CREATE CONSTRAINT TRIGGER b_sounding_results_in_bn_area AFTER INSERT OR UPDATE ON waterway.sounding_results FOR EACH ROW EXECUTE FUNCTION check_sr_in_bn_area(); -- -- FAIRWAY AVAILABILITY -- -- The current implementation associates fairway_availability data -- hard with the internal id of an bottleneck. Lets use the -- bottleneck_id (official unique id) instead and to the lookup of an -- matching bottleneck for a specific date on demand. -- Dear reader: The gemma schema update scripts are intended to be run -- only once, which is implemented via schema verioning and the -- update-db.sh script. None the less it is very helpful to be able -- to run scripts more than once during development and testing, -- without harm being done. Thats the reason for the following code -- to be, like it is: -- -- This migration can only be done once, thanks to psql magic we are -- able to guard it approprieatly. SELECT data_type='integer' AS old_fwa_bnid FROM information_schema.columns WHERE table_schema = 'waterway' AND table_name='fairway_availability' AND column_name='bottleneck_id'; \gset \if :old_fwa_bnid \qecho 'Migrating bottleneck_id column in fairway_availability to text id.' -- We temporarily keep the old if field for the migration of existing data: ALTER TABLE waterway.fairway_availability RENAME COLUMN bottleneck_id TO old_bnid; ALTER TABLE waterway.fairway_availability ADD COLUMN bottleneck_id varchar; -- Migrate existing data: Let's be ultra permissive and make the -- migration _before adding the constraint triggger. UPDATE waterway.fairway_availability AS fwa SET bottleneck_id = b.bottleneck_id FROM waterway.bottlenecks b WHERE b.id = fwa.old_bnid; ALTER TABLE waterway.fairway_availability ALTER COLUMN bottleneck_id SET NOT NULL; -- Set constraint trigger to make sure a matching BN exists: -- -- FIXME: From the DRC it is unclear what the exact semantics of -- surdat and Date_Info ar unclear. Currently we assume that -- (fk_bn_fid,surdat) has to be unique, but that might be false. -- Anyway, I will date_info here to check for an matching -- reference gauge at the bottleneck. The reason for this -- decision is purely practical (and might be semantically -- disputable: the bottleneck data in the demo system is not old -- enough to cover rthe surdat times... CREATE CONSTRAINT TRIGGER fairway_availability_referenced_bottleneck AFTER INSERT OR UPDATE OF bottleneck_id ON waterway.fairway_availability FOR EACH ROW EXECUTE FUNCTION check_valid_bottleneck_ts('bottleneck_id','date_info'); -- Set NOT NULL constraint for new column ALTER TABLE waterway.fairway_availability ALTER COLUMN bottleneck_id SET NOT NULL; -- The change also effects the geoserver bottlenecks view, which -- joined in fairway_availability. We leave the rather fuzzy match -- (not using any validity time match), as it is unclear what the -- validity period of fwa data is. CREATE OR REPLACE VIEW waterway.bottlenecks_geoserver AS SELECT b.id, b.bottleneck_id, b.objnam, b.nobjnm, b.stretch, b.area, b.rb, b.lb, b.responsible_country, b.revisiting_time, b.limiting, b.date_info, b.source_organization, g.location AS gauge_isrs_code, g.objname AS gauge_objname, g.reference_water_levels, fal.date_info AS fa_date_info, fal.critical AS fa_critical, g.gm_measuredate, g.gm_waterlevel, g.gm_n_14d, srl.date_max, g.forecast_accuracy_3d, g.forecast_accuracy_1d FROM waterway.bottlenecks b LEFT JOIN waterway.gauges_base_view g ON b.gauge_location = g.location AND g.validity @> current_timestamp LEFT JOIN (SELECT DISTINCT ON (bottleneck_id) bottleneck_id, date_info, critical FROM waterway.fairway_availability ORDER BY bottleneck_id, date_info DESC) AS fal ON b.bottleneck_id = fal.bottleneck_id LEFT JOIN (SELECT DISTINCT ON (bottleneck_id) bottleneck_id, max(date_info) AS date_max FROM waterway.sounding_results GROUP BY bottleneck_id ORDER BY bottleneck_id DESC) AS srl ON b.bottleneck_id = srl.bottleneck_id WHERE b.validity @> current_timestamp; -- Finally dropt the old column ALTER TABLE waterway.fairway_availability DROP COLUMN old_bnid; ALTER TABLE waterway.fairway_availability ADD CONSTRAINT fairway_availability_bottleneck_id_surdat_key UNIQUE (bottleneck_id, surdat); \else \qecho 'NOTICE: bottleneck_id column in fairway_availability alread migrated.' \endif -- -- DROP NO LONGER NEEDED TRIGGER FUNCTION -- -- This used to update foreign key references. As these references no -- longer exist we dont need this magic any more... DROP TRIGGER IF EXISTS move_referencing ON waterway.bottlenecks; DROP FUNCTION IF EXISTS move_bottleneck_referencing();