Mercurial > gemma
changeset 113:25b28fd0e256
Moved schema stuff to own subfolder.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 26 Jun 2018 16:14:59 +0200 |
parents | 894f633e2d3f |
children | 79f5ba414586 |
files | Dockerfile README auth.sql dot.tmpl schema/Dockerfile schema/README schema/auth.sql schema/dot.tmpl schema/tap_tests.sql schema/tap_tests_data.sql schema/wamos.sql tap_tests.sql tap_tests_data.sql wamos.sql |
diffstat | 14 files changed, 713 insertions(+), 713 deletions(-) [+] |
line wrap: on
line diff
--- a/Dockerfile Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -FROM centos:7 -MAINTAINER tom.gottfried@intevation.de - -# Add the PostgreSQL PGP key to verify the official yum repository packages -RUN rpm --import https://yum.postgresql.org/RPM-GPG-KEY-PGDG-10 - -# Add PostgreSQL's repository. It contains the most recent release -# of PostgreSQL, 10: -RUN yum -q -y install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm - -# Install PostgreSQL 10 and PostGIS -RUN yum -q -y install postgresql10-server -RUN yum -q -y install epel-release -RUN yum -q -y install postgis24_10 pgtap10 - -USER postgres -ENV PGBIN /usr/pgsql-10/bin/ - -# initdb PostgreSQL 10: -ENV PGDATA /var/lib/pgsql/10/data -RUN $PGBIN/initdb -E UTF8 2>&1 < /dev/null - -# Adjust PostgreSQL configuration so that remote connections to the -# database are possible. -ENV PGCONF /var/lib/pgsql/10/data/postgresql.conf -RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/10/data/pg_hba.conf -RUN echo "listen_addresses='*'" >> $PGCONF - -# Expose the PostgreSQL port -EXPOSE 5432 - -# Create WAMOS role and database -ADD *.sql ./ -RUN $PGBIN/pg_ctl start -wo "--config_file=$PGCONF" && \ - psql -c "CREATE USER wamos PASSWORD 'wamos'" && \ - createdb wamos && \ - psql -f wamos.sql -d wamos && \ - psql -f auth.sql -d wamos && \ - $PGBIN/pg_ctl stop -m smart - -# Set the default command to run when starting the container -CMD ["/usr/pgsql-10/bin/postgres", "-D", "/var/lib/pgsql/10/data"]
--- a/README Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -Build Dockerfile with e.g.: -$ docker build -t wamos . - -Get a running instance with e.g.: -$ docker run --name wamos -d -p 54321:5432 -v $PWD:/opt/wamos wamos - -Run tests for RLS policies as database superuser (within container) with: -$ psql -d wamos -Xf tap_tests.sql - -Create ER diagrams with e.g.: -Auxiliary tables: -$ postgresql_autodoc -p 54321 -h $dockerhost \ - -U wamos --password=wamos -t dot -l . -s 'wamos' -$ dot -Tpdf wamos.dot > wamos_auxiliary.pdf - -Waterway related tables: -$ postgresql_autodoc -p 54321 -h $dockerhost \ - -U wamos --password=wamos -t dot -l . -s 'wamos_waterway' -$ dot -Tpdf wamos.dot > wamos_waterway.pdf - -Fairway/bottleneck related tables: -$ postgresql_autodoc -p 54321 -h $dockerhost \ - -U wamos --password=wamos -t dot -l . -s 'wamos_fairway' -$ dot -Tpdf wamos.dot > wamos_fairway.pdf
--- a/auth.sql Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -BEGIN; - --- --- Roles, privileges and policies for the WAMOS database --- -SET search_path TO public, wamos, wamos_waterway, wamos_fairway; - --- We do not want any users to be able to create any objects -REVOKE CREATE ON SCHEMA public FROM PUBLIC; - --- --- Primary WAMOS roles (SRS table 3) --- -CREATE ROLE waterway_user; -CREATE ROLE waterway_admin IN ROLE waterway_user; -CREATE ROLE sys_admin CREATEROLE BYPASSRLS IN ROLE waterway_admin; - --- --- Privileges for waterway_user --- -GRANT USAGE ON SCHEMA wamos, wamos_waterway, wamos_fairway TO waterway_user; -GRANT SELECT ON ALL TABLES IN SCHEMA wamos_waterway, wamos_fairway - TO waterway_user; -GRANT SELECT ON templates, user_templates, user_profiles TO waterway_user; - --- --- Extended privileges for waterway_admin --- -GRANT INSERT, UPDATE ON ALL TABLES IN SCHEMA wamos_waterway, wamos_fairway - TO waterway_admin; --- TODO: will there ever be UPDATEs or can we drop that due to historicisation? -GRANT INSERT, UPDATE ON templates, user_templates TO waterway_admin; -GRANT SELECT ON responsibility_areas TO waterway_admin; - --- --- Extended privileges for sys_admin --- -GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA wamos - TO sys_admin; - --- --- RLS policies for waterway_user --- - --- Staging area -CREATE FUNCTION create_hide_staging_policy() RETURNS void AS $$ -DECLARE the_table varchar; -BEGIN - FOREACH the_table IN ARRAY ARRAY[ - 'bottlenecks', 'sounding_results'] - -- TODO: add all relevant tables here - LOOP - EXECUTE format('CREATE POLICY hide_staging ON %I ' - 'FOR SELECT TO waterway_user USING (staging_done)', the_table); - EXECUTE format('ALTER TABLE %I ENABLE ROW LEVEL SECURITY', the_table); - END LOOP; -END; -$$ LANGUAGE plpgsql; -SELECT create_hide_staging_policy(); -DROP FUNCTION create_hide_staging_policy; - -CREATE POLICY see_yourself ON user_profiles FOR SELECT TO waterway_user - USING (username = current_user); -ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY; - -CREATE POLICY own_templates ON templates FOR SELECT TO waterway_user - USING (id IN(SELECT template_id FROM user_templates - WHERE username = current_user)); -ALTER TABLE templates ENABLE ROW LEVEL SECURITY; - --- --- RLS policies for waterway_admin --- - --- Staging area --- TODO: add all relevant tables here -CREATE POLICY responsibility_area ON bottlenecks FOR ALL TO waterway_admin - USING (ST_Within(area, (SELECT area FROM responsibility_areas - WHERE country = (SELECT country FROM user_profiles)))); -CREATE POLICY responsibility_area ON sounding_results FOR ALL TO waterway_admin - USING (ST_Within(area, (SELECT area FROM responsibility_areas - WHERE country = (SELECT country FROM user_profiles)))); - -CREATE POLICY manage_templates ON templates FOR ALL TO waterway_admin - USING (id IN(SELECT template_id FROM user_templates ut - JOIN user_profiles p ON ut.username = p.username - WHERE p.country = (SELECT country FROM user_profiles))); - -COMMIT;
--- a/dot.tmpl Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -digraph g { -graph [ -rankdir = "LR", -concentrate = true, -ratio = auto -]; -node [ -fontsize = "10", -shape = record -]; -edge [ -]; -<TMPL_LOOP name="schemas"><TMPL_LOOP name="tables"><TMPL_UNLESS name="view_definition"> -"<TMPL_IF name="number_of_schemas"><TMPL_VAR name="schema_dot">.</TMPL_IF name="number_of_schemas"><TMPL_VAR name="table_dot">" [shape = plaintext, label = <<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0"><TR><TD PORT="ltcol0"></TD><TD border="1" COLSPAN="2"> \N </TD><TD PORT="rtcol0"></TD></TR><TMPL_LOOP name="columns"><TR><TD PORT="ltcol<TMPL_VAR name="column_number">"></TD><TD align="left"><TMPL_VAR name="column_dot"></TD><TD align="left"><TMPL_VAR name="column_type"></TD><TD align="left" PORT="rtcol<TMPL_VAR name="column_number">"></TD></TR></TMPL_LOOP name="columns"></TABLE>> ]; -</TMPL_UNLESS name="view_definition"></TMPL_LOOP name="tables"></TMPL_LOOP name="schemas"> - -<TMPL_LOOP name="fk_links"> -"<TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle0_schema">.</TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle0_name">":rtcol<TMPL_VAR name="handle0_connection"> -> "<TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle1_schema">.</TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle1_name">":ltcol<TMPL_VAR name="handle1_connection"> [];</TMPL_LOOP name="fk_links"> -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/Dockerfile Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,42 @@ +FROM centos:7 +MAINTAINER tom.gottfried@intevation.de + +# Add the PostgreSQL PGP key to verify the official yum repository packages +RUN rpm --import https://yum.postgresql.org/RPM-GPG-KEY-PGDG-10 + +# Add PostgreSQL's repository. It contains the most recent release +# of PostgreSQL, 10: +RUN yum -q -y install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm + +# Install PostgreSQL 10 and PostGIS +RUN yum -q -y install postgresql10-server +RUN yum -q -y install epel-release +RUN yum -q -y install postgis24_10 pgtap10 + +USER postgres +ENV PGBIN /usr/pgsql-10/bin/ + +# initdb PostgreSQL 10: +ENV PGDATA /var/lib/pgsql/10/data +RUN $PGBIN/initdb -E UTF8 2>&1 < /dev/null + +# Adjust PostgreSQL configuration so that remote connections to the +# database are possible. +ENV PGCONF /var/lib/pgsql/10/data/postgresql.conf +RUN echo "host all all 0.0.0.0/0 md5" >> /var/lib/pgsql/10/data/pg_hba.conf +RUN echo "listen_addresses='*'" >> $PGCONF + +# Expose the PostgreSQL port +EXPOSE 5432 + +# Create WAMOS role and database +ADD *.sql ./ +RUN $PGBIN/pg_ctl start -wo "--config_file=$PGCONF" && \ + psql -c "CREATE USER wamos PASSWORD 'wamos'" && \ + createdb wamos && \ + psql -f wamos.sql -d wamos && \ + psql -f auth.sql -d wamos && \ + $PGBIN/pg_ctl stop -m smart + +# Set the default command to run when starting the container +CMD ["/usr/pgsql-10/bin/postgres", "-D", "/var/lib/pgsql/10/data"]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/README Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,24 @@ +Build Dockerfile with e.g.: +$ docker build -t wamos . + +Get a running instance with e.g.: +$ docker run --name wamos -d -p 54321:5432 -v $PWD:/opt/wamos wamos + +Run tests for RLS policies as database superuser (within container) with: +$ psql -d wamos -Xf tap_tests.sql + +Create ER diagrams with e.g.: +Auxiliary tables: +$ postgresql_autodoc -p 54321 -h $dockerhost \ + -U wamos --password=wamos -t dot -l . -s 'wamos' +$ dot -Tpdf wamos.dot > wamos_auxiliary.pdf + +Waterway related tables: +$ postgresql_autodoc -p 54321 -h $dockerhost \ + -U wamos --password=wamos -t dot -l . -s 'wamos_waterway' +$ dot -Tpdf wamos.dot > wamos_waterway.pdf + +Fairway/bottleneck related tables: +$ postgresql_autodoc -p 54321 -h $dockerhost \ + -U wamos --password=wamos -t dot -l . -s 'wamos_fairway' +$ dot -Tpdf wamos.dot > wamos_fairway.pdf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/auth.sql Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,89 @@ +BEGIN; + +-- +-- Roles, privileges and policies for the WAMOS database +-- +SET search_path TO public, wamos, wamos_waterway, wamos_fairway; + +-- We do not want any users to be able to create any objects +REVOKE CREATE ON SCHEMA public FROM PUBLIC; + +-- +-- Primary WAMOS roles (SRS table 3) +-- +CREATE ROLE waterway_user; +CREATE ROLE waterway_admin IN ROLE waterway_user; +CREATE ROLE sys_admin CREATEROLE BYPASSRLS IN ROLE waterway_admin; + +-- +-- Privileges for waterway_user +-- +GRANT USAGE ON SCHEMA wamos, wamos_waterway, wamos_fairway TO waterway_user; +GRANT SELECT ON ALL TABLES IN SCHEMA wamos_waterway, wamos_fairway + TO waterway_user; +GRANT SELECT ON templates, user_templates, user_profiles TO waterway_user; + +-- +-- Extended privileges for waterway_admin +-- +GRANT INSERT, UPDATE ON ALL TABLES IN SCHEMA wamos_waterway, wamos_fairway + TO waterway_admin; +-- TODO: will there ever be UPDATEs or can we drop that due to historicisation? +GRANT INSERT, UPDATE ON templates, user_templates TO waterway_admin; +GRANT SELECT ON responsibility_areas TO waterway_admin; + +-- +-- Extended privileges for sys_admin +-- +GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA wamos + TO sys_admin; + +-- +-- RLS policies for waterway_user +-- + +-- Staging area +CREATE FUNCTION create_hide_staging_policy() RETURNS void AS $$ +DECLARE the_table varchar; +BEGIN + FOREACH the_table IN ARRAY ARRAY[ + 'bottlenecks', 'sounding_results'] + -- TODO: add all relevant tables here + LOOP + EXECUTE format('CREATE POLICY hide_staging ON %I ' + 'FOR SELECT TO waterway_user USING (staging_done)', the_table); + EXECUTE format('ALTER TABLE %I ENABLE ROW LEVEL SECURITY', the_table); + END LOOP; +END; +$$ LANGUAGE plpgsql; +SELECT create_hide_staging_policy(); +DROP FUNCTION create_hide_staging_policy; + +CREATE POLICY see_yourself ON user_profiles FOR SELECT TO waterway_user + USING (username = current_user); +ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY; + +CREATE POLICY own_templates ON templates FOR SELECT TO waterway_user + USING (id IN(SELECT template_id FROM user_templates + WHERE username = current_user)); +ALTER TABLE templates ENABLE ROW LEVEL SECURITY; + +-- +-- RLS policies for waterway_admin +-- + +-- Staging area +-- TODO: add all relevant tables here +CREATE POLICY responsibility_area ON bottlenecks FOR ALL TO waterway_admin + USING (ST_Within(area, (SELECT area FROM responsibility_areas + WHERE country = (SELECT country FROM user_profiles)))); +CREATE POLICY responsibility_area ON sounding_results FOR ALL TO waterway_admin + USING (ST_Within(area, (SELECT area FROM responsibility_areas + WHERE country = (SELECT country FROM user_profiles)))); + +CREATE POLICY manage_templates ON templates FOR ALL TO waterway_admin + USING (id IN(SELECT template_id FROM user_templates ut + JOIN user_profiles p ON ut.username = p.username + WHERE p.country = (SELECT country FROM user_profiles))); + +COMMIT;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/dot.tmpl Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,19 @@ +digraph g { +graph [ +rankdir = "LR", +concentrate = true, +ratio = auto +]; +node [ +fontsize = "10", +shape = record +]; +edge [ +]; +<TMPL_LOOP name="schemas"><TMPL_LOOP name="tables"><TMPL_UNLESS name="view_definition"> +"<TMPL_IF name="number_of_schemas"><TMPL_VAR name="schema_dot">.</TMPL_IF name="number_of_schemas"><TMPL_VAR name="table_dot">" [shape = plaintext, label = <<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0"><TR><TD PORT="ltcol0"></TD><TD border="1" COLSPAN="2"> \N </TD><TD PORT="rtcol0"></TD></TR><TMPL_LOOP name="columns"><TR><TD PORT="ltcol<TMPL_VAR name="column_number">"></TD><TD align="left"><TMPL_VAR name="column_dot"></TD><TD align="left"><TMPL_VAR name="column_type"></TD><TD align="left" PORT="rtcol<TMPL_VAR name="column_number">"></TD></TR></TMPL_LOOP name="columns"></TABLE>> ]; +</TMPL_UNLESS name="view_definition"></TMPL_LOOP name="tables"></TMPL_LOOP name="schemas"> + +<TMPL_LOOP name="fk_links"> +"<TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle0_schema">.</TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle0_name">":rtcol<TMPL_VAR name="handle0_connection"> -> "<TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle1_schema">.</TMPL_IF name="number_of_schemas"><TMPL_VAR name="handle1_name">":ltcol<TMPL_VAR name="handle1_connection"> [];</TMPL_LOOP name="fk_links"> +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/tap_tests.sql Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,81 @@ +-- +-- pgTAP test script +-- +BEGIN; + +CREATE EXTENSION pgtap; + +SELECT plan(10); -- Give number of tests that have to be run + +SET search_path TO public, wamos, wamos_waterway, wamos_fairway; + +\i tap_tests_data.sql + +-- +-- Run tests as unprivileged user +-- +SET SESSION AUTHORIZATION waterway_user; + +SELECT throws_ok('CREATE TABLE test()', 42501, NULL, + 'No objects can be created'); + +SELECT isnt_empty('SELECT * FROM bottlenecks', + 'Staged data should be visible'); +SELECT is_empty('SELECT * FROM bottlenecks WHERE NOT staging_done', + 'Only staged data should be visible'); + +SELECT set_eq('SELECT count(*) FROM wamos.user_profiles', ARRAY[1], + 'User should only see his own profile'); +SELECT results_eq('SELECT username FROM user_profiles', + 'SELECT CAST(current_user AS varchar)', + 'User should only see his own profile'); + +SELECT isnt_empty('SELECT * FROM templates', + 'User should see templates associated to him'); +SELECT is_empty('SELECT * FROM templates t + JOIN user_templates ut ON t.id = template_id + WHERE username <> current_user', + 'User should only see templates associated to him'); + +-- +-- Run tests as waterway administrator +-- +SET SESSION AUTHORIZATION waterway_admin; + +PREPARE bn_insert (varchar, geometry(POLYGON, 4326)) AS + INSERT INTO bottlenecks ( + bottleneck_id, fk_g_fid, stretch, area, rb, lb, responsible_country, + revisiting_time, limiting, source_organization) + VALUES + ($1, + ('AT', 'XXX', '00001', '00000', 1)::isrs, + isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs, + ('AT', 'XXX', '00001', '00000', 2)::isrs), + $2, 'AT', 'AT', 'AT', + 1, 'depth', 'testorganization'); +-- XXX: In contrast to what table 240 in the PostgreSQL docs says +-- (https://www.postgresql.org/docs/10/static/sql-createpolicy.html), +-- the following tests seem to show that the USING expression is applied +-- also to an INSERT: +SELECT lives_ok('EXECUTE bn_insert(''test1'', + ST_geomfromtext(''POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'', + 4326))', + 'Waterway admin can insert data within his region'); +SELECT throws_ok('EXECUTE bn_insert(''test2'', + ST_geomfromtext(''POLYGON((1 0, 1 1, 2 1, 2 0, 1 0))'', + 4326))', 42501, NULL, + 'Waterway admin cannot insert data outside his region'); + +-- XXX: Why does this fail? POLICY manage_templates should allow to see +-- the template of waterway_user. +SELECT isnt_empty('SELECT * FROM templates t + JOIN user_templates ut ON t.id = template_id + WHERE username <> current_user', + 'Waterway admin should see templates of users in country'); + +-- +-- finish tests +-- +SELECT * FROM finish(); + +ROLLBACK;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/tap_tests_data.sql Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,49 @@ +SET search_path TO public, wamos, wamos_waterway, wamos_fairway; + +INSERT INTO countries VALUES ('AT'); + +INSERT INTO responsibility_areas VALUES + ('AT', ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)); + +INSERT INTO user_profiles (username, country, email_adress) + VALUES + ('waterway_user', 'AT', 'xxx'), + ('waterway_admin', 'AT', 'yyy'), + ('sys_admin', 'AT', 'zzz'); + +INSERT INTO limiting_factors VALUES ('depth'), ('width'); + +INSERT INTO gauges ( + location, function_code, objname, geom, zero_point, source_organization) + VALUES + (('AT', 'XXX', '00001', '00000', 1)::isrs, + 'xxx', + 'testgauge', + ST_geomfromtext('POINT(0 0)', 4326), + 0, + 'testorganization'); + +INSERT INTO bottlenecks ( + bottleneck_id, fk_g_fid, stretch, area, rb, lb, responsible_country, + revisiting_time, limiting, source_organization, staging_done) + VALUES + ('testbottleneck1', + ('AT', 'XXX', '00001', '00000', 1)::isrs, + isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs, + ('AT', 'XXX', '00001', '00000', 2)::isrs), + ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326), + 'AT', 'AT', 'AT', + 1, 'depth', 'testorganization', false), + ('testbottleneck2', + ('AT', 'XXX', '00001', '00000', 1)::isrs, + isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs, + ('AT', 'XXX', '00001', '00000', 2)::isrs), + ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326), + 'AT', 'AT', 'AT', + 1, 'depth', 'testorganization', true); + +INSERT INTO templates (dummy_attrib) + VALUES ('usertemplate'), ('othertemplate'); +INSERT INTO user_templates + SELECT 'waterway_user', id FROM templates + WHERE dummy_attrib = 'usertemplate';
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/wamos.sql Tue Jun 26 16:14:59 2018 +0200 @@ -0,0 +1,409 @@ +BEGIN; + +-- +-- Infrastructure +-- +CREATE EXTENSION postgis; + +-- TODO: will there ever be UPDATEs or can we drop that function due to +-- historicisation? +CREATE FUNCTION update_date_info() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + NEW.date_info = CURRENT_TIMESTAMP; + RETURN NEW; + END; +$$; + +-- Composite type: UN/LOCODE, fairway section, object reference, hectometre. +-- See RIS-Index Encoding Guide +CREATE TYPE isrs AS ( + country_code char(2), -- ISO 3166 country code + -- could be validated against countries table. + locode char(3), -- without the country code: + -- http://www.unece.org/cefact/locode/welcome.html + fairway_section char(5), + object_reference char(5), + hectometre int -- should be constrained to five digits +); + +CREATE TYPE isrsrange AS RANGE ( + subtype = isrs + ); + +-- +-- WAMOS data +-- +CREATE SCHEMA wamos; +CREATE SCHEMA wamos_waterway; +CREATE SCHEMA wamos_fairway; +SET search_path TO public, wamos, wamos_waterway, wamos_fairway; +-- TODO: consolidate schemas. The current distribution of tables is mainly +-- for diagram generation. A privilege based distribution might ease +-- privilege management. + +-- +-- Auxiliary tables +-- +CREATE TABLE wamos.system_config ( + config_key varchar PRIMARY KEY, + config_val varchar + ); + +CREATE TABLE wamos.countries ( + country_code char(2) PRIMARY KEY -- ISO 3166 country code + -- A smallint PK would require even less disk space i.e. on the FK side. + -- This might be an issue in case cache space becomes a limiting + -- factor when there are many FKs pointing here. + ); + +CREATE TABLE wamos.responsibility_areas ( + country char(2) PRIMARY KEY REFERENCES countries, + area geometry(POLYGON, 4326) --XXX: Should be geography (elsewhere too) + ); + +CREATE TABLE wamos.language_codes ( + language_code varchar PRIMARY KEY + ); + +CREATE TABLE wamos.user_profiles ( + username varchar PRIMARY KEY, -- TODO: check it's in pg_roles by trigger + country char(2) NOT NULL REFERENCES countries, + language_code varchar REFERENCES language_codes, + map_extent box2d, + email_adress varchar NOT NULL UNIQUE + ); + +CREATE TABLE wamos.templates ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + dummy_attrib varchar, + "..." varchar + -- TODO: template attributes tbd. + ); + +CREATE TABLE wamos.user_templates ( + username varchar NOT NULL REFERENCES user_profiles, + template_id int NOT NULL REFERENCES templates, + PRIMARY KEY (username, template_id) + ); + +-- +-- General river information +-- + +-- Eventually obsolete. +-- See https://roundup-intern.intevation.de/wamos/issue5 +-- CREATE TABLE rwdrs ( +-- stretch isrsrange PRIMARY KEY, +-- -- https://www.postgresql.org/docs/10/static/sql-createindex.html: +-- -- Only B-tree supports UNIQUE indexes, but we need the GIST index +-- -- below anyhow. +-- -- Is it a good idea to build B-tree indexes on relatively large +-- -- composites of string values or should we use inter PKs? +-- -- => In case the index is used and cache space becomes a limiting +-- -- factor, this might be an issue. +-- rwdr double precision NOT NULL, +-- EXCLUDE USING GIST (stretch WITH &&) +-- ); + +CREATE TABLE wamos_waterway.catccls ( + catccl smallint PRIMARY KEY + -- TODO: Do we need name and/or definition from IENC feature catalogue? + ); + +CREATE TABLE wamos_waterway.dirimps ( + dirimp smallint PRIMARY KEY + -- TODO: Do we need name and/or definition from IENC feature catalogue? + ); + +CREATE TABLE wamos_waterway.waterway_area ( + area geometry(POLYGON, 4326) PRIMARY KEY, + catccl smallint REFERENCES catccls, + dirimp smallint REFERENCES dirimps + ); + +CREATE TABLE wamos_fairway.depth_references ( + depth_reference varchar(4) PRIMARY KEY + -- See col. AB and AI RIS-Index Encoding Guide + -- XXX: We need a way to distinguish between geodetic (eg. col. AP + -- RIS-Index) and other references (e.g. col. AB and AI): + -- _ multi-column FK with a boolean column (geodetic/non-geodetic; + -- i.e. absolut/not absolut) and DEFAULTs and CHECKs at the FK side. + -- _ Do not mixup things with different meanings in one table at all + -- (which would mean a model differing a bit from RIS-Index ideas) + ); + +CREATE TABLE wamos_fairway.reference_water_levels ( + reference_water_level varchar(20) PRIMARY KEY + ); + +CREATE TABLE wamos_fairway.gauges ( + location isrs PRIMARY KEY, + function_code varchar(10) NOT NULL, -- XXX: What is this really for? + objname varchar NOT NULL, + is_left boolean, -- XXX: Or reference position_codes? + geom geometry(POINT, 4326) NOT NULL, + applicability isrsrange, + validity tstzrange, -- XXX: Should ranges be NOT NULL? In DRC, only copy + -- pasted text from a more general specification is given + -- (a gauge is not a berth!) + -- TODO: Ranges need a joint exclusion constaint to prevent overlaps? + zero_point double precision NOT NULL, + geodref varchar(4) REFERENCES depth_references, + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL + ); +CREATE TRIGGER gauges_date_info BEFORE UPDATE ON gauges + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +CREATE TABLE wamos_fairway.gauges_reference_water_levels ( + gauge_id isrs NOT NULL REFERENCES gauges, + reference_water_level varchar(20) + NOT NULL REFERENCES reference_water_levels, + PRIMARY KEY (gauge_id, reference_water_level), + value int NOT NULL + ); + +CREATE TABLE wamos_fairway.gauge_measurements ( + fk_gauge_id isrs NOT NULL REFERENCES gauges, + measure_date timestamp with time zone NOT NULL, + PRIMARY KEY (fk_gauge_id, measure_date), + -- XXX: Is country_code really relevant for WAMOS or just NtS? + -- country_code char(2) NOT NULL REFERENCES countries, + -- TODO: add relations to stuff provided as enumerations + sender varchar NOT NULL, -- "from" attribute from DRC + language_code varchar NOT NULL REFERENCES language_codes, + date_issue timestamp with time zone NOT NULL, + -- reference_code varchar(4) NOT NULL REFERENCES depth_references, + -- XXX: Always ZPG? + water_level double precision NOT NULL, + predicted boolean NOT NULL, + is_waterlevel boolean NOT NULL, + -- XXX: "measure_code" if really only W or Q + -- XXX: Do we need "unit" attribute or can we normalise on import? + value_min double precision, -- XXX: NOT NULL if predicted? + value_max double precision, -- XXX: NOT NULL if predicted? + --- TODO: Add a double range type for checking? + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL -- "originator" + ); +CREATE TRIGGER gauge_measurements_date_info BEFORE UPDATE ON gauge_measurements + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +CREATE TABLE wamos_waterway.waterway_axis ( + wtwaxs geometry(LINESTRING, 4326) PRIMARY KEY, + -- TODO: Do we need to check data set quality as described in DRC 2.1.6? + objnam varchar NOT NULL, + nobjnam varchar + ); + +CREATE TABLE wamos_waterway.distance_mark_functions ( + -- XXX: Redundant information to object code in isrs code of dist. mark + distance_mark_function varchar(8) PRIMARY KEY + ); + +CREATE TABLE wamos_waterway.position_codes ( + position_code char(2) PRIMARY KEY + -- Use smallint because of fairway availability provided on daily basis? + -- Data come from 2015_06_23_RIS_Index_template_v2p0.xlsx, + -- sheet "Position_code" or RIS-Index encoding guide? + -- XXX: DRC 2.1.7 and 2.2.5 _seem_ to reference the same thing here. + -- Clarify! + -- TODO: Do we need an attribute "meaning" or so? + ); + +-- This table allows linkage between the 1D ISRS location codes and 2D space +-- e.g. for cutting bottleneck area out of waterway area based on virtual +-- distance marks along waterway axis (see SUC7). +CREATE TABLE wamos_waterway.distance_marks ( + location_code isrs PRIMARY KEY, + geom geometry(POINT, 4326) NOT NULL, + distance_mark_function varchar(8) + NOT NULL REFERENCES distance_mark_functions, + -- XXX: attribute "function" in DRC 2.1.7 as well as CATDIS seem + -- to encode the same thing as the object code in ISRS location code. + position_code char(2) NOT NULL REFERENCES position_codes + ); + +CREATE TABLE wamos_waterway.sections_stretches ( + id varchar PRIMARY KEY, + is_section boolean NOT NULL, -- maps 'function' from interface + stretch isrsrange, + objnam varchar NOT NULL, + nobjnam varchar, + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL + ); +CREATE TRIGGER sections_stretches_date_info BEFORE UPDATE ON sections_stretches + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +CREATE TABLE wamos_waterway.waterway_profiles ( + location isrs NOT NULL, + validity tstzrange, + EXCLUDE USING GIST (validity WITH &&), + PRIMARY KEY (location, validity), + lnwl smallint, + mwl smallint, + hnwl smallint, + fe30 smallint, + fe100 smallint, + -- XXX: further normalise using reference_water_levels? + CHECK(COALESCE(lnwl, mwl, hnwl, fe30, fe100) IS NULL + OR validity IS NOT NULL), + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL + ); +CREATE TRIGGER waterway_profiles_date_info BEFORE UPDATE ON waterway_profiles + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +CREATE TABLE wamos_waterway.levels_of_service ( + level_of_service smallint PRIMARY KEY + ); + +CREATE TABLE wamos_waterway.fairway_dimensions ( + area geometry(POLYGON, 4326) PRIMARY KEY, + level_of_service smallint NOT NULL REFERENCES levels_of_service, + min_width smallint NOT NULL, + max_width smallint NOT NULL, + min_depth smallint NOT NULL, + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL + ); +CREATE TRIGGER fairway_dimensions_date_info BEFORE UPDATE ON fairway_dimensions + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +-- +-- Bottlenecks +-- +CREATE TABLE wamos_fairway.riverbed_materials ( + material varchar PRIMARY KEY + -- XXX: Should this table contain choices from DRC 2.2.3 or + -- from IENC Encoding Guide M.4.3, attribute NATSUR? + ); + +CREATE TABLE wamos_fairway.survey_types ( + survey_type varchar PRIMARY KEY + ); + +CREATE TABLE wamos_fairway.coverage_types ( + coverage_type varchar PRIMARY KEY + ); + +CREATE TABLE wamos_fairway.limiting_factors ( + limiting_factor varchar PRIMARY KEY + ); + +-- XXX: Nullability differs between DRC (attributes marked "O") and WSDL +-- (minOccurs=0; nillable seems to be set arbitrarily as even bottleneck_id and +-- fk_g_fid (both mandatory, i.e. marked "M" in DRC) have nillable="true" in WSDL) +CREATE TABLE wamos_fairway.bottlenecks ( + bottleneck_id varchar PRIMARY KEY, + fk_g_fid isrs NOT NULL REFERENCES gauges, + -- XXX: DRC references "ch. 3.1.1", which does not exist in document. + objnam varchar, + nobjnm varchar, + stretch isrsrange NOT NULL, + area geometry(POLYGON, 4326) NOT NULL, + rb char(2) NOT NULL REFERENCES countries, -- from rb_lb in interface + lb char(2) NOT NULL REFERENCES countries, -- from rb_lb in interface + responsible_country char(2) NOT NULL REFERENCES countries, + revisiting_time smallint NOT NULL, + limiting varchar NOT NULL REFERENCES limiting_factors, + -- surtyp varchar NOT NULL REFERENCES survey_types, + -- XXX: Also an attribut of sounding result? + -- coverage varchar REFERENCES coverage_types, + -- XXX: Also an attribut of sounding result? + -- CHECK allowed combinations of surtyp and coverage or + -- different model approach? + -- depth_reference char(3) NOT NULL REFERENCES depth_references, + -- XXX: Also an attribut of sounding result? + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL, + -- additional_data xml -- Currently not relevant for WAMOS + staging_done boolean NOT NULL DEFAULT false + ); +CREATE TRIGGER bottleneck_date_info BEFORE UPDATE ON bottlenecks + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +CREATE TABLE wamos_fairway.bottlenecks_riverbed_materials ( + bottleneck_id varchar REFERENCES bottlenecks, + riverbed varchar REFERENCES riverbed_materials, + -- XXX: should be 'natsur' according to IENC Encoding Guide M.4.3 + PRIMARY KEY (bottleneck_id, riverbed) + ); + +CREATE TABLE wamos_fairway.sounding_results ( + bottleneck_id varchar NOT NULL REFERENCES bottlenecks, + date_info date NOT NULL, + PRIMARY KEY (bottleneck_id, date_info), + area geometry(POLYGON, 4326) NOT NULL, + surtyp varchar NOT NULL REFERENCES survey_types, + coverage varchar REFERENCES coverage_types, + depth_reference char(3) NOT NULL REFERENCES depth_references, + sounding_data raster NOT NULL, + staging_done boolean NOT NULL DEFAULT false + ); + +-- +-- Fairway availability +-- +CREATE TABLE wamos_fairway.measure_types ( + measure_type varchar PRIMARY KEY + ); + +CREATE TABLE wamos_fairway.fairway_availability ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + position_code char(2) REFERENCES position_codes, + bottleneck_id varchar NOT NULL REFERENCES bottlenecks, + surdat date NOT NULL, + UNIQUE (bottleneck_id, surdat), + -- additional_data xml -- Currently not relevant for WAMOS + critical boolean, + date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + source_organization varchar NOT NULL + ); +CREATE TRIGGER fairway_availability_date_info + BEFORE UPDATE ON fairway_availability + FOR EACH ROW EXECUTE PROCEDURE update_date_info(); + +CREATE TABLE wamos_fairway.fa_reference_values ( + fairway_availability_id int NOT NULL REFERENCES fairway_availability, + level_of_service smallint NOT NULL REFERENCES levels_of_service, + PRIMARY KEY (fairway_availability_id, level_of_service), + fairway_depth smallint, + fairway_width smallint, + fairway_radius int, + CHECK(COALESCE(fairway_depth, fairway_width, fairway_radius) IS NOT NULL), + shallowest_spot geometry(POINT, 4326) + ); + +CREATE TABLE wamos_fairway.bottleneck_pdfs ( + fairway_availability_id int NOT NULL REFERENCES fairway_availability, + profile_pdf_filename varchar NOT NULL, -- redundant to last part of URL + profile_pdf_url varchar NOT NULL, -- prohibit insecure URLs somehow? + PRIMARY KEY (fairway_availability_id, profile_pdf_url), + pdf_generation_date timestamp with time zone NOT NULL, + source_organization varchar NOT NULL + ); + +CREATE TABLE wamos_fairway.effective_fairway_availability ( + fairway_availability_id int NOT NULL REFERENCES fairway_availability, + measure_date timestamp with time zone NOT NULL, + level_of_service smallint NOT NULL REFERENCES levels_of_service, + PRIMARY KEY (fairway_availability_id, measure_date, level_of_service), + available_depth_value smallint, + available_width_value smallint, + water_level_value smallint, + CHECK(COALESCE(available_depth_value, available_width_value, + water_level_value) IS NOT NULL), + measure_type varchar NOT NULL REFERENCES measure_types, + source_organization varchar NOT NULL, + forecast_generation_time timestamp with time zone, + CHECK(measure_type <> 'forecasted' + OR forecast_generation_time IS NOT NULL), + value_lifetime timestamp with time zone, + CHECK(measure_type = 'minimum guaranteed' OR value_lifetime IS NOT NULL) + ); + +COMMIT;
--- a/tap_tests.sql Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ --- --- pgTAP test script --- -BEGIN; - -CREATE EXTENSION pgtap; - -SELECT plan(10); -- Give number of tests that have to be run - -SET search_path TO public, wamos, wamos_waterway, wamos_fairway; - -\i tap_tests_data.sql - --- --- Run tests as unprivileged user --- -SET SESSION AUTHORIZATION waterway_user; - -SELECT throws_ok('CREATE TABLE test()', 42501, NULL, - 'No objects can be created'); - -SELECT isnt_empty('SELECT * FROM bottlenecks', - 'Staged data should be visible'); -SELECT is_empty('SELECT * FROM bottlenecks WHERE NOT staging_done', - 'Only staged data should be visible'); - -SELECT set_eq('SELECT count(*) FROM wamos.user_profiles', ARRAY[1], - 'User should only see his own profile'); -SELECT results_eq('SELECT username FROM user_profiles', - 'SELECT CAST(current_user AS varchar)', - 'User should only see his own profile'); - -SELECT isnt_empty('SELECT * FROM templates', - 'User should see templates associated to him'); -SELECT is_empty('SELECT * FROM templates t - JOIN user_templates ut ON t.id = template_id - WHERE username <> current_user', - 'User should only see templates associated to him'); - --- --- Run tests as waterway administrator --- -SET SESSION AUTHORIZATION waterway_admin; - -PREPARE bn_insert (varchar, geometry(POLYGON, 4326)) AS - INSERT INTO bottlenecks ( - bottleneck_id, fk_g_fid, stretch, area, rb, lb, responsible_country, - revisiting_time, limiting, source_organization) - VALUES - ($1, - ('AT', 'XXX', '00001', '00000', 1)::isrs, - isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs, - ('AT', 'XXX', '00001', '00000', 2)::isrs), - $2, 'AT', 'AT', 'AT', - 1, 'depth', 'testorganization'); --- XXX: In contrast to what table 240 in the PostgreSQL docs says --- (https://www.postgresql.org/docs/10/static/sql-createpolicy.html), --- the following tests seem to show that the USING expression is applied --- also to an INSERT: -SELECT lives_ok('EXECUTE bn_insert(''test1'', - ST_geomfromtext(''POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'', - 4326))', - 'Waterway admin can insert data within his region'); -SELECT throws_ok('EXECUTE bn_insert(''test2'', - ST_geomfromtext(''POLYGON((1 0, 1 1, 2 1, 2 0, 1 0))'', - 4326))', 42501, NULL, - 'Waterway admin cannot insert data outside his region'); - --- XXX: Why does this fail? POLICY manage_templates should allow to see --- the template of waterway_user. -SELECT isnt_empty('SELECT * FROM templates t - JOIN user_templates ut ON t.id = template_id - WHERE username <> current_user', - 'Waterway admin should see templates of users in country'); - --- --- finish tests --- -SELECT * FROM finish(); - -ROLLBACK;
--- a/tap_tests_data.sql Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -SET search_path TO public, wamos, wamos_waterway, wamos_fairway; - -INSERT INTO countries VALUES ('AT'); - -INSERT INTO responsibility_areas VALUES - ('AT', ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)); - -INSERT INTO user_profiles (username, country, email_adress) - VALUES - ('waterway_user', 'AT', 'xxx'), - ('waterway_admin', 'AT', 'yyy'), - ('sys_admin', 'AT', 'zzz'); - -INSERT INTO limiting_factors VALUES ('depth'), ('width'); - -INSERT INTO gauges ( - location, function_code, objname, geom, zero_point, source_organization) - VALUES - (('AT', 'XXX', '00001', '00000', 1)::isrs, - 'xxx', - 'testgauge', - ST_geomfromtext('POINT(0 0)', 4326), - 0, - 'testorganization'); - -INSERT INTO bottlenecks ( - bottleneck_id, fk_g_fid, stretch, area, rb, lb, responsible_country, - revisiting_time, limiting, source_organization, staging_done) - VALUES - ('testbottleneck1', - ('AT', 'XXX', '00001', '00000', 1)::isrs, - isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs, - ('AT', 'XXX', '00001', '00000', 2)::isrs), - ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326), - 'AT', 'AT', 'AT', - 1, 'depth', 'testorganization', false), - ('testbottleneck2', - ('AT', 'XXX', '00001', '00000', 1)::isrs, - isrsrange(('AT', 'XXX', '00001', '00000', 0)::isrs, - ('AT', 'XXX', '00001', '00000', 2)::isrs), - ST_geomfromtext('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326), - 'AT', 'AT', 'AT', - 1, 'depth', 'testorganization', true); - -INSERT INTO templates (dummy_attrib) - VALUES ('usertemplate'), ('othertemplate'); -INSERT INTO user_templates - SELECT 'waterway_user', id FROM templates - WHERE dummy_attrib = 'usertemplate';
--- a/wamos.sql Fri Jun 15 20:20:44 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,409 +0,0 @@ -BEGIN; - --- --- Infrastructure --- -CREATE EXTENSION postgis; - --- TODO: will there ever be UPDATEs or can we drop that function due to --- historicisation? -CREATE FUNCTION update_date_info() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - NEW.date_info = CURRENT_TIMESTAMP; - RETURN NEW; - END; -$$; - --- Composite type: UN/LOCODE, fairway section, object reference, hectometre. --- See RIS-Index Encoding Guide -CREATE TYPE isrs AS ( - country_code char(2), -- ISO 3166 country code - -- could be validated against countries table. - locode char(3), -- without the country code: - -- http://www.unece.org/cefact/locode/welcome.html - fairway_section char(5), - object_reference char(5), - hectometre int -- should be constrained to five digits -); - -CREATE TYPE isrsrange AS RANGE ( - subtype = isrs - ); - --- --- WAMOS data --- -CREATE SCHEMA wamos; -CREATE SCHEMA wamos_waterway; -CREATE SCHEMA wamos_fairway; -SET search_path TO public, wamos, wamos_waterway, wamos_fairway; --- TODO: consolidate schemas. The current distribution of tables is mainly --- for diagram generation. A privilege based distribution might ease --- privilege management. - --- --- Auxiliary tables --- -CREATE TABLE wamos.system_config ( - config_key varchar PRIMARY KEY, - config_val varchar - ); - -CREATE TABLE wamos.countries ( - country_code char(2) PRIMARY KEY -- ISO 3166 country code - -- A smallint PK would require even less disk space i.e. on the FK side. - -- This might be an issue in case cache space becomes a limiting - -- factor when there are many FKs pointing here. - ); - -CREATE TABLE wamos.responsibility_areas ( - country char(2) PRIMARY KEY REFERENCES countries, - area geometry(POLYGON, 4326) --XXX: Should be geography (elsewhere too) - ); - -CREATE TABLE wamos.language_codes ( - language_code varchar PRIMARY KEY - ); - -CREATE TABLE wamos.user_profiles ( - username varchar PRIMARY KEY, -- TODO: check it's in pg_roles by trigger - country char(2) NOT NULL REFERENCES countries, - language_code varchar REFERENCES language_codes, - map_extent box2d, - email_adress varchar NOT NULL UNIQUE - ); - -CREATE TABLE wamos.templates ( - id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - dummy_attrib varchar, - "..." varchar - -- TODO: template attributes tbd. - ); - -CREATE TABLE wamos.user_templates ( - username varchar NOT NULL REFERENCES user_profiles, - template_id int NOT NULL REFERENCES templates, - PRIMARY KEY (username, template_id) - ); - --- --- General river information --- - --- Eventually obsolete. --- See https://roundup-intern.intevation.de/wamos/issue5 --- CREATE TABLE rwdrs ( --- stretch isrsrange PRIMARY KEY, --- -- https://www.postgresql.org/docs/10/static/sql-createindex.html: --- -- Only B-tree supports UNIQUE indexes, but we need the GIST index --- -- below anyhow. --- -- Is it a good idea to build B-tree indexes on relatively large --- -- composites of string values or should we use inter PKs? --- -- => In case the index is used and cache space becomes a limiting --- -- factor, this might be an issue. --- rwdr double precision NOT NULL, --- EXCLUDE USING GIST (stretch WITH &&) --- ); - -CREATE TABLE wamos_waterway.catccls ( - catccl smallint PRIMARY KEY - -- TODO: Do we need name and/or definition from IENC feature catalogue? - ); - -CREATE TABLE wamos_waterway.dirimps ( - dirimp smallint PRIMARY KEY - -- TODO: Do we need name and/or definition from IENC feature catalogue? - ); - -CREATE TABLE wamos_waterway.waterway_area ( - area geometry(POLYGON, 4326) PRIMARY KEY, - catccl smallint REFERENCES catccls, - dirimp smallint REFERENCES dirimps - ); - -CREATE TABLE wamos_fairway.depth_references ( - depth_reference varchar(4) PRIMARY KEY - -- See col. AB and AI RIS-Index Encoding Guide - -- XXX: We need a way to distinguish between geodetic (eg. col. AP - -- RIS-Index) and other references (e.g. col. AB and AI): - -- _ multi-column FK with a boolean column (geodetic/non-geodetic; - -- i.e. absolut/not absolut) and DEFAULTs and CHECKs at the FK side. - -- _ Do not mixup things with different meanings in one table at all - -- (which would mean a model differing a bit from RIS-Index ideas) - ); - -CREATE TABLE wamos_fairway.reference_water_levels ( - reference_water_level varchar(20) PRIMARY KEY - ); - -CREATE TABLE wamos_fairway.gauges ( - location isrs PRIMARY KEY, - function_code varchar(10) NOT NULL, -- XXX: What is this really for? - objname varchar NOT NULL, - is_left boolean, -- XXX: Or reference position_codes? - geom geometry(POINT, 4326) NOT NULL, - applicability isrsrange, - validity tstzrange, -- XXX: Should ranges be NOT NULL? In DRC, only copy - -- pasted text from a more general specification is given - -- (a gauge is not a berth!) - -- TODO: Ranges need a joint exclusion constaint to prevent overlaps? - zero_point double precision NOT NULL, - geodref varchar(4) REFERENCES depth_references, - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL - ); -CREATE TRIGGER gauges_date_info BEFORE UPDATE ON gauges - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - -CREATE TABLE wamos_fairway.gauges_reference_water_levels ( - gauge_id isrs NOT NULL REFERENCES gauges, - reference_water_level varchar(20) - NOT NULL REFERENCES reference_water_levels, - PRIMARY KEY (gauge_id, reference_water_level), - value int NOT NULL - ); - -CREATE TABLE wamos_fairway.gauge_measurements ( - fk_gauge_id isrs NOT NULL REFERENCES gauges, - measure_date timestamp with time zone NOT NULL, - PRIMARY KEY (fk_gauge_id, measure_date), - -- XXX: Is country_code really relevant for WAMOS or just NtS? - -- country_code char(2) NOT NULL REFERENCES countries, - -- TODO: add relations to stuff provided as enumerations - sender varchar NOT NULL, -- "from" attribute from DRC - language_code varchar NOT NULL REFERENCES language_codes, - date_issue timestamp with time zone NOT NULL, - -- reference_code varchar(4) NOT NULL REFERENCES depth_references, - -- XXX: Always ZPG? - water_level double precision NOT NULL, - predicted boolean NOT NULL, - is_waterlevel boolean NOT NULL, - -- XXX: "measure_code" if really only W or Q - -- XXX: Do we need "unit" attribute or can we normalise on import? - value_min double precision, -- XXX: NOT NULL if predicted? - value_max double precision, -- XXX: NOT NULL if predicted? - --- TODO: Add a double range type for checking? - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL -- "originator" - ); -CREATE TRIGGER gauge_measurements_date_info BEFORE UPDATE ON gauge_measurements - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - -CREATE TABLE wamos_waterway.waterway_axis ( - wtwaxs geometry(LINESTRING, 4326) PRIMARY KEY, - -- TODO: Do we need to check data set quality as described in DRC 2.1.6? - objnam varchar NOT NULL, - nobjnam varchar - ); - -CREATE TABLE wamos_waterway.distance_mark_functions ( - -- XXX: Redundant information to object code in isrs code of dist. mark - distance_mark_function varchar(8) PRIMARY KEY - ); - -CREATE TABLE wamos_waterway.position_codes ( - position_code char(2) PRIMARY KEY - -- Use smallint because of fairway availability provided on daily basis? - -- Data come from 2015_06_23_RIS_Index_template_v2p0.xlsx, - -- sheet "Position_code" or RIS-Index encoding guide? - -- XXX: DRC 2.1.7 and 2.2.5 _seem_ to reference the same thing here. - -- Clarify! - -- TODO: Do we need an attribute "meaning" or so? - ); - --- This table allows linkage between the 1D ISRS location codes and 2D space --- e.g. for cutting bottleneck area out of waterway area based on virtual --- distance marks along waterway axis (see SUC7). -CREATE TABLE wamos_waterway.distance_marks ( - location_code isrs PRIMARY KEY, - geom geometry(POINT, 4326) NOT NULL, - distance_mark_function varchar(8) - NOT NULL REFERENCES distance_mark_functions, - -- XXX: attribute "function" in DRC 2.1.7 as well as CATDIS seem - -- to encode the same thing as the object code in ISRS location code. - position_code char(2) NOT NULL REFERENCES position_codes - ); - -CREATE TABLE wamos_waterway.sections_stretches ( - id varchar PRIMARY KEY, - is_section boolean NOT NULL, -- maps 'function' from interface - stretch isrsrange, - objnam varchar NOT NULL, - nobjnam varchar, - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL - ); -CREATE TRIGGER sections_stretches_date_info BEFORE UPDATE ON sections_stretches - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - -CREATE TABLE wamos_waterway.waterway_profiles ( - location isrs NOT NULL, - validity tstzrange, - EXCLUDE USING GIST (validity WITH &&), - PRIMARY KEY (location, validity), - lnwl smallint, - mwl smallint, - hnwl smallint, - fe30 smallint, - fe100 smallint, - -- XXX: further normalise using reference_water_levels? - CHECK(COALESCE(lnwl, mwl, hnwl, fe30, fe100) IS NULL - OR validity IS NOT NULL), - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL - ); -CREATE TRIGGER waterway_profiles_date_info BEFORE UPDATE ON waterway_profiles - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - -CREATE TABLE wamos_waterway.levels_of_service ( - level_of_service smallint PRIMARY KEY - ); - -CREATE TABLE wamos_waterway.fairway_dimensions ( - area geometry(POLYGON, 4326) PRIMARY KEY, - level_of_service smallint NOT NULL REFERENCES levels_of_service, - min_width smallint NOT NULL, - max_width smallint NOT NULL, - min_depth smallint NOT NULL, - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL - ); -CREATE TRIGGER fairway_dimensions_date_info BEFORE UPDATE ON fairway_dimensions - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - --- --- Bottlenecks --- -CREATE TABLE wamos_fairway.riverbed_materials ( - material varchar PRIMARY KEY - -- XXX: Should this table contain choices from DRC 2.2.3 or - -- from IENC Encoding Guide M.4.3, attribute NATSUR? - ); - -CREATE TABLE wamos_fairway.survey_types ( - survey_type varchar PRIMARY KEY - ); - -CREATE TABLE wamos_fairway.coverage_types ( - coverage_type varchar PRIMARY KEY - ); - -CREATE TABLE wamos_fairway.limiting_factors ( - limiting_factor varchar PRIMARY KEY - ); - --- XXX: Nullability differs between DRC (attributes marked "O") and WSDL --- (minOccurs=0; nillable seems to be set arbitrarily as even bottleneck_id and --- fk_g_fid (both mandatory, i.e. marked "M" in DRC) have nillable="true" in WSDL) -CREATE TABLE wamos_fairway.bottlenecks ( - bottleneck_id varchar PRIMARY KEY, - fk_g_fid isrs NOT NULL REFERENCES gauges, - -- XXX: DRC references "ch. 3.1.1", which does not exist in document. - objnam varchar, - nobjnm varchar, - stretch isrsrange NOT NULL, - area geometry(POLYGON, 4326) NOT NULL, - rb char(2) NOT NULL REFERENCES countries, -- from rb_lb in interface - lb char(2) NOT NULL REFERENCES countries, -- from rb_lb in interface - responsible_country char(2) NOT NULL REFERENCES countries, - revisiting_time smallint NOT NULL, - limiting varchar NOT NULL REFERENCES limiting_factors, - -- surtyp varchar NOT NULL REFERENCES survey_types, - -- XXX: Also an attribut of sounding result? - -- coverage varchar REFERENCES coverage_types, - -- XXX: Also an attribut of sounding result? - -- CHECK allowed combinations of surtyp and coverage or - -- different model approach? - -- depth_reference char(3) NOT NULL REFERENCES depth_references, - -- XXX: Also an attribut of sounding result? - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL, - -- additional_data xml -- Currently not relevant for WAMOS - staging_done boolean NOT NULL DEFAULT false - ); -CREATE TRIGGER bottleneck_date_info BEFORE UPDATE ON bottlenecks - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - -CREATE TABLE wamos_fairway.bottlenecks_riverbed_materials ( - bottleneck_id varchar REFERENCES bottlenecks, - riverbed varchar REFERENCES riverbed_materials, - -- XXX: should be 'natsur' according to IENC Encoding Guide M.4.3 - PRIMARY KEY (bottleneck_id, riverbed) - ); - -CREATE TABLE wamos_fairway.sounding_results ( - bottleneck_id varchar NOT NULL REFERENCES bottlenecks, - date_info date NOT NULL, - PRIMARY KEY (bottleneck_id, date_info), - area geometry(POLYGON, 4326) NOT NULL, - surtyp varchar NOT NULL REFERENCES survey_types, - coverage varchar REFERENCES coverage_types, - depth_reference char(3) NOT NULL REFERENCES depth_references, - sounding_data raster NOT NULL, - staging_done boolean NOT NULL DEFAULT false - ); - --- --- Fairway availability --- -CREATE TABLE wamos_fairway.measure_types ( - measure_type varchar PRIMARY KEY - ); - -CREATE TABLE wamos_fairway.fairway_availability ( - id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - position_code char(2) REFERENCES position_codes, - bottleneck_id varchar NOT NULL REFERENCES bottlenecks, - surdat date NOT NULL, - UNIQUE (bottleneck_id, surdat), - -- additional_data xml -- Currently not relevant for WAMOS - critical boolean, - date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - source_organization varchar NOT NULL - ); -CREATE TRIGGER fairway_availability_date_info - BEFORE UPDATE ON fairway_availability - FOR EACH ROW EXECUTE PROCEDURE update_date_info(); - -CREATE TABLE wamos_fairway.fa_reference_values ( - fairway_availability_id int NOT NULL REFERENCES fairway_availability, - level_of_service smallint NOT NULL REFERENCES levels_of_service, - PRIMARY KEY (fairway_availability_id, level_of_service), - fairway_depth smallint, - fairway_width smallint, - fairway_radius int, - CHECK(COALESCE(fairway_depth, fairway_width, fairway_radius) IS NOT NULL), - shallowest_spot geometry(POINT, 4326) - ); - -CREATE TABLE wamos_fairway.bottleneck_pdfs ( - fairway_availability_id int NOT NULL REFERENCES fairway_availability, - profile_pdf_filename varchar NOT NULL, -- redundant to last part of URL - profile_pdf_url varchar NOT NULL, -- prohibit insecure URLs somehow? - PRIMARY KEY (fairway_availability_id, profile_pdf_url), - pdf_generation_date timestamp with time zone NOT NULL, - source_organization varchar NOT NULL - ); - -CREATE TABLE wamos_fairway.effective_fairway_availability ( - fairway_availability_id int NOT NULL REFERENCES fairway_availability, - measure_date timestamp with time zone NOT NULL, - level_of_service smallint NOT NULL REFERENCES levels_of_service, - PRIMARY KEY (fairway_availability_id, measure_date, level_of_service), - available_depth_value smallint, - available_width_value smallint, - water_level_value smallint, - CHECK(COALESCE(available_depth_value, available_width_value, - water_level_value) IS NOT NULL), - measure_type varchar NOT NULL REFERENCES measure_types, - source_organization varchar NOT NULL, - forecast_generation_time timestamp with time zone, - CHECK(measure_type <> 'forecasted' - OR forecast_generation_time IS NOT NULL), - value_lifetime timestamp with time zone, - CHECK(measure_type = 'minimum guaranteed' OR value_lifetime IS NOT NULL) - ); - -COMMIT;