diff --git a/datamodel/app/create_app.py b/datamodel/app/create_app.py index a041b9f66..a89ef7965 100755 --- a/datamodel/app/create_app.py +++ b/datamodel/app/create_app.py @@ -70,10 +70,11 @@ def create_app( run_sql_file("functions/modification_functions.sql", pg_service) run_sql_file("functions/symbology_functions.sql", pg_service) run_sql_file("functions/reach_direction_change.sql", pg_service, variables) - run_sql_file("functions/14_geometry_functions.sql", pg_service, variables) + run_sql_file("functions/geometry_functions.sql", pg_service, variables) run_sql_file("functions/update_catchment_area_totals.sql", pg_service, variables) run_sql_file("functions/organisation_functions.sql", pg_service, variables) run_sql_file("functions/meta_functions.sql", pg_service, variables) + run_sql_file("functions/network_functions.sql", pg_service) # open YAML files if tww_reach_extra: @@ -134,6 +135,8 @@ def create_app( "drainage_system": "zone", } + # Defaults and Triggers + # Has to be fired before view creation otherwise it won't work and will only fail in CI set_defaults_and_triggers(pg_service, SingleInheritances) for key in SingleInheritances: @@ -245,8 +248,7 @@ def create_app( pg_service, ).create() - run_sql_file("triggers/network.sql", pg_service) - + # Roles run_sql_file("tww_app_roles.sql", pg_service, variables) diff --git a/datamodel/app/functions/14_geometry_functions.sql b/datamodel/app/functions/geometry_functions.sql similarity index 100% rename from datamodel/app/functions/14_geometry_functions.sql rename to datamodel/app/functions/geometry_functions.sql diff --git a/datamodel/app/functions/modification_functions.sql b/datamodel/app/functions/modification_functions.sql index 02bf13cac..307cf174f 100644 --- a/datamodel/app/functions/modification_functions.sql +++ b/datamodel/app/functions/modification_functions.sql @@ -1,26 +1,6 @@ ------- LAST MODIFIED ----- -CREATE FUNCTION tww_app.modification_last_modified() RETURNS trigger AS $$ -BEGIN - NEW.last_modification := TIMEOFDAY(); - - RETURN NEW; -END; -$$ LANGUAGE PLPGSQL; - -CREATE FUNCTION tww_app.modification_last_modified_parent() RETURNS trigger AS $$ -DECLARE - table_name TEXT; -BEGIN - table_name = TG_ARGV[0]; - - EXECUTE ' - UPDATE ' || table_name || ' - SET last_modification = TIMEOFDAY()::timestamp - WHERE obj_id = ''' || NEW.obj_id || ''' -'; - RETURN NEW; -END; -$$ LANGUAGE PLPGSQL; +-------------------------------------------------- +-- Alter modification triggers +-------------------------------------------------- CREATE OR REPLACE FUNCTION tww_app.alter_modification_triggers(action_name text) RETURNS VOID AS $DO$ @@ -53,6 +33,10 @@ END; $DO$ LANGUAGE plpgsql SECURITY DEFINER; +-------------------------------------------------- +-- Check if modification triggers are enabled +-------------------------------------------------- + CREATE OR REPLACE FUNCTION tww_app.check_modification_enabled() RETURNS BOOL AS $DO$ DECLARE _disabled_count numeric; @@ -70,3 +54,72 @@ BEGIN END; $DO$ LANGUAGE plpgsql SECURITY DEFINER; + +-------------------------------------------------- +-- ON REACH DELETE +-------------------------------------------------- +-- Remove linked network element and reach points +-- Remove channel if no reach is left +-------------------------------------------------- + +CREATE OR REPLACE FUNCTION tww_app.modification_on_reach_delete() + RETURNS trigger AS +$BODY$ +DECLARE + channel_id text; + reach_count integer; +BEGIN + -- get channel obj_id + SELECT fk_wastewater_structure INTO channel_id + FROM tww_od.wastewater_networkelement + WHERE wastewater_networkelement.obj_id = OLD.obj_id; + + DELETE FROM tww_od.wastewater_networkelement WHERE obj_id = OLD.obj_id; + DELETE FROM tww_od.reach_point WHERE obj_id = OLD.fk_reach_point_from; + DELETE FROM tww_od.reach_point WHERE obj_id = OLD.fk_reach_point_to; + + -- delete channel if no reach left + SELECT COUNT(fk_wastewater_structure) INTO reach_count + FROM tww_od.wastewater_networkelement + WHERE fk_wastewater_structure = channel_id; + IF reach_count = 0 THEN + RAISE NOTICE 'Removing channel (%) since no reach is left', channel_id; + DELETE FROM tww_od.channel WHERE obj_id = channel_id; + DELETE FROM tww_od.wastewater_structure WHERE obj_id = channel_id; + END IF; + RETURN NEW; +END; $BODY$ +LANGUAGE plpgsql VOLATILE; + +CREATE TRIGGER on_reach_1_delete +AFTER DELETE + ON tww_od.reach + FOR EACH ROW + EXECUTE PROCEDURE tww_app.modification_on_reach_delete(); + +-------------------------------------------------- +-- LAST MODIFIED +-------------------------------------------------- + +CREATE FUNCTION tww_app.modification_last_modified() RETURNS trigger AS $$ +BEGIN + NEW.last_modification := TIMEOFDAY(); + + RETURN NEW; +END; +$$ LANGUAGE PLPGSQL; + +CREATE FUNCTION tww_app.modification_last_modified_parent() RETURNS trigger AS $$ +DECLARE + table_name TEXT; +BEGIN + table_name = TG_ARGV[0]; + + EXECUTE ' + UPDATE ' || table_name || ' + SET last_modification = TIMEOFDAY()::timestamp + WHERE obj_id = ''' || NEW.obj_id || ''' +'; + RETURN NEW; +END; +$$ LANGUAGE PLPGSQL; diff --git a/datamodel/app/triggers/network.sql b/datamodel/app/functions/network_functions.sql similarity index 100% rename from datamodel/app/triggers/network.sql rename to datamodel/app/functions/network_functions.sql diff --git a/datamodel/app/functions/symbology_functions.sql b/datamodel/app/functions/symbology_functions.sql index d64244ad3..4ce6ee14c 100644 --- a/datamodel/app/functions/symbology_functions.sql +++ b/datamodel/app/functions/symbology_functions.sql @@ -134,6 +134,8 @@ $BODY$ LANGUAGE plpgsql VOLATILE; + + -------------------------------------------------------- -- UPDATE wastewater node symbology by overflow -- Argument: @@ -204,7 +206,9 @@ $BODY$ LANGUAGE plpgsql VOLATILE; - -------------------- SYMBOLOGY UPDATE ON CHANNEL TABLE CHANGES ---------------------- +-------------------------------------------------------- +-- SYMBOLOGY UPDATE ON CHANNEL TABLE CHANGES +-------------------------------------------------------- CREATE OR REPLACE FUNCTION tww_app.symbology_update_by_channel() RETURNS trigger AS @@ -257,8 +261,16 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; +CREATE TRIGGER ws_symbology_update_by_channel +AFTER INSERT OR UPDATE OR DELETE +ON tww_od.channel +FOR EACH ROW +EXECUTE PROCEDURE tww_app.symbology_update_by_channel(); - -------------------- SYMBOLOGY UPDATE ON REACH POINT TABLE CHANGES ---------------------- + +-------------------------------------------------------- +-- SYMBOLOGY UPDATE ON REACH POINT TABLE CHANGES +-------------------------------------------------------- CREATE OR REPLACE FUNCTION tww_app.symbology_update_by_reach_point() RETURNS trigger AS @@ -294,7 +306,18 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; - -------------------- SYMBOLOGY UPDATE ON REACH TABLE CHANGES ---------------------- +-- only update -> insert and delete are handled by reach trigger +CREATE TRIGGER ws_symbology_update_by_reach_point +AFTER UPDATE + ON tww_od.reach_point +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_update_by_reach_point(); + + + +-------------------------------------------------------- +-- SYMBOLOGY UPDATE ON REACH TABLE CHANGES +-------------------------------------------------------- CREATE OR REPLACE FUNCTION tww_app.ws_symbology_update_by_reach() RETURNS trigger AS @@ -342,11 +365,16 @@ BEGIN RAISE EXCEPTION 'TRIGGER ERROR ws_symbology_update_by_reach. Subquery shoud return exactly one row. This is not supposed to happen and indicates an isue with the trigger. The issue must be fixed in TWW.'; END; - RETURN NEW; END; $BODY$ LANGUAGE plpgsql VOLATILE; +CREATE TRIGGER ws_symbology_update_by_reach +AFTER INSERT OR UPDATE OR DELETE + ON tww_od.reach +FOR EACH ROW + EXECUTE PROCEDURE tww_app.ws_symbology_update_by_reach(); + -------------------------------------------------------- -- UPDATE wastewater structure fk_main_cover -- Argument: @@ -552,6 +580,8 @@ $BODY$ LANGUAGE plpgsql VOLATILE; + + -------------------------------------------------- -- ON COVER CHANGE -------------------------------------------------- @@ -584,7 +614,11 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; - +CREATE TRIGGER on_cover_change +AFTER INSERT OR UPDATE OR DELETE + ON tww_od.cover +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_cover_change(); -------------------------------------------------- @@ -616,6 +650,17 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; +CREATE TRIGGER ws_label_update_by_wastewater_networkelement +AFTER INSERT OR UPDATE OR DELETE + ON tww_od.wastewater_networkelement +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_structure_part_change_networkelement(); + +CREATE TRIGGER on_structure_part_change +AFTER INSERT OR UPDATE OR DELETE + ON tww_od.structure_part +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_structure_part_change_networkelement(); -------------------------------------------------- @@ -644,6 +689,12 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; +CREATE TRIGGER on_wastewater_structure_update +AFTER UPDATE + ON tww_od.wastewater_structure +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_wastewater_structure_update(); + -------------------------------------------------- -- ON REACH CHANGE -------------------------------------------------- @@ -680,39 +731,12 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; +CREATE TRIGGER on_reach_2_change +AFTER INSERT OR UPDATE OR DELETE + ON tww_od.reach +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_reach_change(); --------------------------------------------------- --- ON REACH DELETE --------------------------------------------------- - -CREATE OR REPLACE FUNCTION tww_app.symbology_on_reach_delete() - RETURNS trigger AS -$BODY$ -DECLARE - channel_id text; - reach_count integer; -BEGIN - -- get channel obj_id - SELECT fk_wastewater_structure INTO channel_id - FROM tww_od.wastewater_networkelement - WHERE wastewater_networkelement.obj_id = OLD.obj_id; - - DELETE FROM tww_od.wastewater_networkelement WHERE obj_id = OLD.obj_id; - DELETE FROM tww_od.reach_point WHERE obj_id = OLD.fk_reach_point_from; - DELETE FROM tww_od.reach_point WHERE obj_id = OLD.fk_reach_point_to; - - -- delete channel if no reach left - SELECT COUNT(fk_wastewater_structure) INTO reach_count - FROM tww_od.wastewater_networkelement - WHERE fk_wastewater_structure = channel_id; - IF reach_count = 0 THEN - RAISE NOTICE 'Removing channel (%) since no reach is left', channel_id; - DELETE FROM tww_od.channel WHERE obj_id = channel_id; - DELETE FROM tww_od.wastewater_structure WHERE obj_id = channel_id; - END IF; - RETURN NEW; -END; $BODY$ -LANGUAGE plpgsql VOLATILE; -------------------------------------------------- -- ON WASTEWATER NODE CHANGE @@ -745,6 +769,12 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; +CREATE TRIGGER on_wasterwaternode_change +AFTER INSERT OR UPDATE + ON tww_od.wastewater_node +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_wastewater_node_change(); + -------------------------------------------------- -- ON REACH POINT CHANGE -------------------------------------------------- @@ -793,6 +823,13 @@ BEGIN END; $BODY$ LANGUAGE plpgsql VOLATILE; +-- only update -> insert and delete are handled by reach trigger +CREATE TRIGGER on_reach_point_update +AFTER UPDATE + ON tww_od.reach_point +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_on_reach_point_update(); + -------------------------------------------------- -- CALCULATE REACH LENGTH -------------------------------------------------- @@ -822,81 +859,11 @@ BEGIN END IF; RETURN NEW; -END; -$BODY$ - LANGUAGE plpgsql VOLATILE; - +END; $BODY$ +LANGUAGE plpgsql VOLATILE; --- only update -> insert and delete are handled by reach trigger - CREATE TRIGGER on_reach_point_update - AFTER UPDATE - ON tww_od.reach_point - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_reach_point_update(); - - CREATE TRIGGER on_reach_2_change - AFTER INSERT OR UPDATE OR DELETE - ON tww_od.reach - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_reach_change(); - - CREATE TRIGGER on_reach_1_delete - AFTER DELETE - ON tww_od.reach - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_reach_delete(); - - CREATE TRIGGER calculate_reach_length - BEFORE INSERT OR UPDATE - ON tww_od.reach - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_calculate_reach_length(); - - CREATE TRIGGER ws_symbology_update_by_reach - AFTER INSERT OR UPDATE OR DELETE - ON tww_od.reach - FOR EACH ROW - EXECUTE PROCEDURE tww_app.ws_symbology_update_by_reach(); - - CREATE TRIGGER on_wastewater_structure_update - AFTER UPDATE - ON tww_od.wastewater_structure - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_wastewater_structure_update(); - - CREATE TRIGGER ws_label_update_by_wastewater_networkelement - AFTER INSERT OR UPDATE OR DELETE - ON tww_od.wastewater_networkelement - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_structure_part_change_networkelement(); - - CREATE TRIGGER on_structure_part_change - AFTER INSERT OR UPDATE OR DELETE - ON tww_od.structure_part - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_structure_part_change_networkelement(); - - CREATE TRIGGER on_cover_change - AFTER INSERT OR UPDATE OR DELETE - ON tww_od.cover - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_cover_change(); - - CREATE TRIGGER on_wasterwaternode_change - AFTER INSERT OR UPDATE - ON tww_od.wastewater_node - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_on_wastewater_node_change(); - - CREATE TRIGGER ws_symbology_update_by_channel - AFTER INSERT OR UPDATE OR DELETE - ON tww_od.channel - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_update_by_channel(); - - -- only update -> insert and delete are handled by reach trigger - CREATE TRIGGER ws_symbology_update_by_reach_point - AFTER UPDATE - ON tww_od.reach_point - FOR EACH ROW - EXECUTE PROCEDURE tww_app.symbology_update_by_reach_point(); +CREATE TRIGGER calculate_reach_length +BEFORE INSERT OR UPDATE + ON tww_od.reach +FOR EACH ROW + EXECUTE PROCEDURE tww_app.symbology_calculate_reach_length();