diff --git a/.env b/.env index 335fff6..36f79f5 100644 --- a/.env +++ b/.env @@ -1,7 +1,7 @@ # This file defines default environment variables for all images # Use 3-part patch version to ignore patch updates, e.g. 5.0.0 -TOOLS_VERSION=5.1 +TOOLS_VERSION=5.2 # Make sure these values are in sync with the ones in .env-postgres file PGDATABASE=openmaptiles @@ -10,13 +10,16 @@ PGPASSWORD=openmaptiles PGHOST=postgres PGPORT=5432 -QUICKSTART_MIN_ZOOM=0 -QUICKSTART_MAX_ZOOM=7 -DIFF_MODE=false - +# BBOX may get overwritten by the computed bbox of the specific area: +# make generate-dc-config BBOX=-180.0,-85.0511,180.0,85.0511 + +# Which zooms to generate in make generate-tiles MIN_ZOOM=0 -MAX_ZOOM=14 +MAX_ZOOM=7 + +# Use true (case sensitive) to allow data updates +DIFF_MODE=false # Hide some output from Mapnik tile generation for clarity FILTER_MAPNIK_OUTPUT=1 @@ -24,3 +27,17 @@ FILTER_MAPNIK_OUTPUT=1 # Some area data like openstreetmap.fr can contain invalid references # that must be cleaned up before using it for borders -- set it to true. BORDERS_CLEANUP=false + +# The current setup assumes this file is placed inside the data/ dir +MBTILES_FILE=tiles.mbtiles +# This is the current repl_config.json location, pre-configured in the tools Dockerfile +# Makefile and quickstart replace it with the dynamically generated one, but we keep it here in case some other method is used to run. +IMPOSM_CONFIG_FILE=/usr/src/app/config/repl_config.json + +# import-borders temp files - set them here to defaults, and override in the Makefile based on the area +BORDERS_CLEANUP_FILE=data/borders/cleanup.pbf +BORDERS_PBF_FILE=data/borders/filtered.pbf +BORDERS_CSV_FILE=data/borders/lines.csv + +# Number of parallel processes to use when importing sql files +MAX_PARALLEL_PSQL=5 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c807573..1828869 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,12 +20,12 @@ jobs: - name: Run quickstart for a small area env: area: monaco - QUICKSTART_MIN_ZOOM: 0 - QUICKSTART_MAX_ZOOM: 14 + MIN_ZOOM: 0 + MAX_ZOOM: 14 run: | - # For now, change the quickstart values directly in the .env file - # TODO: We should probably use env vars instead - sed -i 's/QUICKSTART_MAX_ZOOM=7/QUICKSTART_MAX_ZOOM=14/g' .env + # For now, change the quickstart values directly in the .env file + # TODO: We should probably use env vars instead + sed -i 's/MAX_ZOOM=7/MAX_ZOOM=14/g' .env export QUIET=1 ./quickstart.sh $area @@ -42,10 +42,7 @@ jobs: performance: name: Evaluate performance - runs-on: ubuntu-latest - # Even though we technically don't need to wait for integrity test to finish, - # there is no point to run long perf test until we know the code is OK - needs: integrity_test + runs-on: self-hosted env: ## Smaller tests (runs everything in about 30 minutes) ## Two test areas: equatorial-guinea and liechtenstein @@ -173,7 +170,7 @@ jobs: create_db() { make clean make init-dirs - cp ../ci_cache/perf-test-areas-latest.osm.pbf data/perf-test-areas-latest.osm.pbf + cp ../ci_cache/perf-test-areas-latest.osm.pbf data/perf-test-areas.osm.pbf make destroy-db make all make start-db diff --git a/Makefile b/Makefile index da57ccd..a4887b9 100644 --- a/Makefile +++ b/Makefile @@ -1,44 +1,48 @@ +# +# First section - common variable initialization +# + # Ensure that errors don't hide inside pipes SHELL = /bin/bash .SHELLFLAGS = -o pipefail -c +# Make all .env variables available for make targets +include .env + # Options to run with docker and docker-compose - ensure the container is destroyed on exit # Containers run as the current user rather than root (so that created files are not root-owned) -DC_OPTS?=--rm -u $(shell id -u):$(shell id -g) +DC_OPTS ?= --rm -u $(shell id -u):$(shell id -g) DC_USER?=openmaptiles DC_PASSWORD?=openmaptiles # If set to a non-empty value, will use postgis-preloaded instead of postgis docker image -USE_PRELOADED_IMAGE?= - -# If set, this file will be imported in the import-osm target -PBF_FILE?= +USE_PRELOADED_IMAGE ?= # Local port to use with postserve -PPORT?=8090 +PPORT ?= 8090 export PPORT # Local port to use with tileserver -TPORT?=8081 +TPORT ?= 8081 export TPORT # Allow a custom docker-compose project name ifeq ($(strip $(DC_PROJECT)),) - override DC_PROJECT:=$(notdir $(shell pwd)) - DOCKER_COMPOSE:= docker-compose + DC_PROJECT := $(notdir $(shell pwd)) + DOCKER_COMPOSE := docker-compose else - DOCKER_COMPOSE:= docker-compose --project-name $(DC_PROJECT) + DOCKER_COMPOSE := docker-compose --project-name $(DC_PROJECT) endif # Make some operations quieter (e.g. inside the test script) ifeq ($(strip $(QUIET)),) - QUIET_FLAG:= + QUIET_FLAG := else - QUIET_FLAG:=--quiet + QUIET_FLAG := --quiet endif # Use `xargs --no-run-if-empty` flag, if supported -XARGS:=xargs $(shell xargs --no-run-if-empty /dev/null && echo --no-run-if-empty) +XARGS := xargs $(shell xargs --no-run-if-empty /dev/null && echo --no-run-if-empty) # If running in the test mode, compare files rather than copy them TEST_MODE?=no @@ -50,12 +54,109 @@ else GRAPH_PARAMS=./layers endif +# Set OpenMapTiles host +OMT_HOST := http://$(firstword $(subst :, ,$(subst tcp://,,$(DOCKER_HOST))) localhost) + +# This defines an easy $(newline) value to act as a "\n". Make sure to keep exactly two empty lines after newline. +define newline + + +endef + + +# +# Determine area to work on +# If $(area) parameter is not set and data/*.osm.pbf finds only one file, use it as $(area). +# Otherwise all make targets requiring area param will show an error. +# Note: If there are no data files, and user calls make download area=... once, +# they will not need to use area= parameter after that because there will be just a single file. +# + +# historically we have been using $(area) rather than $(AREA), so make both work +area ?= $(AREA) +# Ensure the $(AREA) param is set, or try to automatically determine it based on available data files +ifeq ($(strip $(area)),) + # if $area is not set. set it to the name of the *.osm.pbf file, but only if there is only one + data_files := $(wildcard data/*.osm.pbf) + ifneq ($(word 2,$(data_files)),) + AREA_ERROR := The 'area' parameter (or env var) has not been set, and there are more than one data/*.osm.pbf files: $(patsubst data/%.osm.pbf,'%',$(data_files)) + else + ifeq ($(word 1,$(data_files)),) + AREA_ERROR := The 'area' parameter (or env var) has not been set, and there are no data/*.osm.pbf files + else + # Keep just the name of the data file, without the .osm.pbf extension + area := $(strip $(basename $(basename $(notdir $(data_files))))) + # Rename area-latest.osm.pbf to area.osm.pbf + # TODO: This if statement could be removed in a few months once everyone is using the file without the `-latest`? + ifneq ($(area),$(area:-latest=)) + $(shell mv "data/$(area).osm.pbf" "data/$(area:-latest=).osm.pbf") + area := $(area:-latest=) + $(warning ATTENTION: File data/$(area)-latest.osm.pbf was renamed to $(area).osm.pbf.) + AREA_INFO := Detected area=$(area) based on the found data/$(area)-latest.osm.pbf (renamed to $(area).osm.pbf). Use 'area' parameter (or env var) to override. + else + AREA_INFO := Detected area=$(area) based on the found data/ pbf file. Use 'area' parameter (or env var) to override. + endif + endif + endif +endif + +# If set, this file will be downloaded in download-osm and imported in the import-osm targets +PBF_FILE ?= data/$(area).osm.pbf + +# For download-osm, allow URL parameter to download file from a given URL. Area param must still be provided. +ifneq ($(strip $(url)),) + DOWNLOAD_AREA := $(url) +else + DOWNLOAD_AREA := $(area) +endif + +# import-borders uses these temp files during border parsing/import +export BORDERS_CLEANUP_FILE ?= data/borders/$(area).cleanup.pbf +export BORDERS_PBF_FILE ?= data/borders/$(area).filtered.pbf +export BORDERS_CSV_FILE ?= data/borders/$(area).lines.csv + +# The file is placed into the $EXPORT_DIR=/export (mapped to ./data) +export MBTILES_FILE ?= $(area).mbtiles +MBTILES_LOCAL_FILE = data/$(MBTILES_FILE) + +ifeq ($(strip $(DIFF_MODE)),true) + # import-osm implementation requires IMPOSM_CONFIG_FILE to be set to a valid file + # For static (no-updates) import, we don't need to override the default value + # For the update mode, set location of the dynamically-generated area-based config file + export IMPOSM_CONFIG_FILE = data/$(area).repl.json +endif + +# download-osm generates this file with metadata about the file +AREA_DC_CONFIG_FILE ?= data/$(area).dc-config.yml + +ifeq ($(strip $(area)),) + define assert_area_is_given + @echo "" + @echo "ERROR: $(AREA_ERROR)" + @echo "" + @echo " make $@ area=" + @echo "" + @echo "To download an area, use make download " + @echo "To list downloadable areas, use make list-geofabrik and/or make list-bbbike" + @exit 1 + endef +else + ifneq ($(strip $(AREA_INFO)),) + define assert_area_is_given + @echo "$(AREA_INFO)" + endef + endif +endif + + + +# +# TARGETS +# + .PHONY: all all: init-dirs build/openmaptiles.tm2source/data.yml build/mapping.yaml build-sql -# Set OpenMapTiles host -OMT_HOST:=http://$(firstword $(subst :, ,$(subst tcp://,,$(DOCKER_HOST))) localhost) - .PHONY: help help: @echo "==============================================================================" @@ -72,9 +173,12 @@ help: @echo "Hints for developers:" @echo " make # build source code" @echo " make list-geofabrik # list actual geofabrik OSM extracts for download" - @echo " make download-geofabrik area=albania # download OSM data from geofabrik, and create config file" - @echo " make download-osmfr area=asia/qatar # download OSM data from openstreetmap.fr, and create config file" - @echo " make download-bbike area=Amsterdam # download OSM data from bbike.org, and create config file" + @echo " make list-bbbike # list actual BBBike OSM extracts for download" + @echo " make download area=albania # download OSM data from any source and create config file" + @echo " make download-geofabrik area=albania # download OSM data from geofabrik.de and create config file" + @echo " make download-osmfr area=asia/qatar # download OSM data from openstreetmap.fr and create config file" + @echo " make download-bbbike area=Amsterdam # download OSM data from bbbike.org and create config file" + @echo " make generate-dc-config # scan data file and generate tile generation config file with bbox" @echo " make psql # start PostgreSQL console" @echo " make psql-list-tables # list all PostgreSQL tables" @echo " make vacuum-db # PostgreSQL: VACUUM ANALYZE" @@ -98,29 +202,39 @@ help: .PHONY: init-dirs init-dirs: - @mkdir -p build/sql - @mkdir -p data + @mkdir -p build/sql/parallel + @mkdir -p build/openmaptiles.tm2source + @mkdir -p data/borders @mkdir -p cache build/openmaptiles.tm2source/data.yml: init-dirs - mkdir -p build/openmaptiles.tm2source +ifeq (,$(wildcard build/openmaptiles.tm2source/data.yml)) $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-tm2source openmaptiles.yaml --host="postgres" --port=5432 --database="openmaptiles" --user="$(DC_USER)" --password="$(DC_PASSWORD)" > $@ +endif build/mapping.yaml: init-dirs +ifeq (,$(wildcard build/mapping.yaml)) $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-imposm3 openmaptiles.yaml > $@ +endif .PHONY: build-sql build-sql: init-dirs +ifeq (,$(wildcard build/sql/run_last.sql)) + @mkdir -p build/sql/parallel $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools bash -c \ 'generate-sql openmaptiles.yaml --dir ./build/sql \ - && generate-sqltomvt openmaptiles.yaml --key --postgis-ver 2.4.8 --function --fname=getmvt >> "./build/sql/run_last.sql"' + && generate-sqltomvt openmaptiles.yaml \ + --key --gzip --postgis-ver 3.0.1 \ + --function --fname=getmvt >> ./build/sql/run_last.sql' +endif .PHONY: clean clean: rm -rf build .PHONY: destroy-db -destroy-db: override DC_PROJECT:=$(shell echo $(DC_PROJECT) | tr A-Z a-z) +# TODO: Use https://stackoverflow.com/a/27852388/177275 +destroy-db: DC_PROJECT := $(shell echo $(DC_PROJECT) | tr A-Z a-z) destroy-db: $(DOCKER_COMPOSE) down -v --remove-orphans $(DOCKER_COMPOSE) rm -fv @@ -152,29 +266,63 @@ stop-db: list-geofabrik: init-dirs $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm list geofabrik -OSM_SERVERS:=geofabrik osmfr bbbike -ALL_DOWNLOADS:=$(addprefix download-,$(OSM_SERVERS)) -OSM_SERVER=$(patsubst download-%,%,$@) +.PHONY: list-bbbike +list-bbbike: init-dirs + $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm list bbbike + +# +# download, download-geofabrik, download-osmfr, and download-bbbike are handled here +# The --imposm-cfg will fail for some of the sources, but we ignore that error -- only needed for diff mode +# +OSM_SERVERS := geofabrik osmfr bbbike +ALL_DOWNLOADS := $(addprefix download-,$(OSM_SERVERS)) download +OSM_SERVER=$(patsubst download,,$(patsubst download-%,%,$@)) .PHONY: $(ALL_DOWNLOADS) $(ALL_DOWNLOADS): init-dirs -ifeq ($(strip $(area)),) + @$(assert_area_is_given) +ifneq ($(strip $(url)),) + $(if $(OSM_SERVER),$(error url parameter can only be used with non-specific download target:$(newline) make download area=$(area) url="$(url)"$(newline))) +endif +ifeq (,$(wildcard $(PBF_FILE))) + ifeq ($(strip $(DIFF_MODE)),true) + @echo "Downloading $(DOWNLOAD_AREA) with replication support into $(PBF_FILE) and $(IMPOSM_CONFIG_FILE) from $(if $(OSM_SERVER),$(OSM_SERVER),any source)" + @$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm $(OSM_SERVER) "$(DOWNLOAD_AREA)" \ + --imposm-cfg "$(IMPOSM_CONFIG_FILE)" \ + --output "$(PBF_FILE)" + else + @echo "Downloading $(DOWNLOAD_AREA) into $(PBF_FILE) from $(if $(OSM_SERVER),$(OSM_SERVER),any source)" + @$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools download-osm $(OSM_SERVER) "$(DOWNLOAD_AREA)" \ + --output "$(PBF_FILE)" + endif @echo "" - @echo "ERROR: Unable to download an area if area is not given." - @echo "Usage:" - @echo " make download-$(OSM_SERVER) area=" - @echo "" - $(if $(filter %-geofabrik,$@),@echo "Use make list-geofabrik to get a list of all available areas";echo "") - @exit 1 else - @echo "=============== download-$(OSM_SERVER) =======================" - @echo "Download area: $(area)" - $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools bash -c \ - 'download-osm $(OSM_SERVER) $(area) \ - --minzoom $$QUICKSTART_MIN_ZOOM \ - --maxzoom $$QUICKSTART_MAX_ZOOM \ - --make-dc /import/docker-compose-config.yml -- -d /import' - ls -la ./data/$(notdir $(area))* - @echo "" + ifeq ($(strip $(DIFF_MODE)),true) + ifeq (,$(wildcard $(IMPOSM_CONFIG_FILE))) + $(error \ + $(newline) Data files $(PBF_FILE) already exists, but $(IMPOSM_CONFIG_FILE) does not. \ + $(newline) You probably downloaded the data file before setting DIFF_MODE=true. \ + $(newline) You can delete the data file $(PBF_FILE) and re-run make download \ + $(newline) to re-download and generate config, or manually create $(IMPOSM_CONFIG_FILE) \ + $(newline) See example https://github.com/openmaptiles/openmaptiles-tools/blob/v5.2/bin/config/repl_config.json \ + $(newline)) + else + @echo "Data files $(PBF_FILE) and replication config $(IMPOSM_CONFIG_FILE) already exists, skipping the download." + endif + else + @echo "Data files $(PBF_FILE) already exists, skipping the download." + endif +endif + +.PHONY: generate-dc-config +generate-dc-config: + @$(assert_area_is_given) +ifeq (,$(wildcard $(AREA_DC_CONFIG_FILE))) + @$(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools bash -c ' \ + download-osm make-dc "$(PBF_FILE)" \ + --make-dc "$(AREA_DC_CONFIG_FILE)" \ + --id "$(area)"' +else + @echo "Configuration file $(AREA_DC_CONFIG_FILE) already exists, no need to regenerate." endif .PHONY: psql @@ -183,14 +331,17 @@ psql: start-db-nowait .PHONY: import-osm import-osm: all start-db-nowait + @$(assert_area_is_given) $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-osm $(PBF_FILE)' .PHONY: update-osm update-osm: all start-db-nowait + @$(assert_area_is_given) $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-update' .PHONY: import-diff import-diff: all start-db-nowait + @$(assert_area_is_given) $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-diff' .PHONY: import-data @@ -199,27 +350,28 @@ import-data: start-db .PHONY: import-borders import-borders: start-db-nowait - $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-borders' + @$(assert_area_is_given) + # If CSV borders file already exists, use it without re-parsing + $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c \ + 'pgwait && import-borders $$([ -f "$(BORDERS_CSV_FILE)" ] && echo load $(BORDERS_CSV_FILE) || echo import $(PBF_FILE))' .PHONY: import-sql import-sql: all start-db-nowait $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools sh -c 'pgwait && import-sql' | \ awk -v s=": WARNING:" '$$0~s{print; print "\n*** WARNING detected, aborting"; exit(1)} 1' -.PHONY: show-metadata -show-metadata: init-dirs - $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools mbtiles-tools meta-all ./data/tiles.mbtiles - -.PHONY: generate-tiles -ifneq ($(wildcard data/docker-compose-config.yml),) - DC_CONFIG_TILES:=-f docker-compose.yml -f ./data/docker-compose-config.yml +ifneq ($(wildcard $(AREA_DC_CONFIG_FILE)),) + DC_CONFIG_TILES := -f docker-compose.yml -f $(AREA_DC_CONFIG_FILE) endif +.PHONY: generate-tiles generate-tiles: all start-db - rm -rf data/tiles.mbtiles - echo "Generating tiles ..."; \ + @$(assert_area_is_given) + @echo "Generating tiles into $(MBTILES_LOCAL_FILE) (will delete if already exists)..." + @rm -rf "$(MBTILES_LOCAL_FILE)" $(DOCKER_COMPOSE) $(DC_CONFIG_TILES) run $(DC_OPTS) generate-vectortiles @echo "Updating generated tile metadata ..." - $(DOCKER_COMPOSE) run $(DC_OPTS) openmaptiles-tools generate-metadata ./data/tiles.mbtiles + $(DOCKER_COMPOSE) $(DC_CONFIG_TILES) run $(DC_OPTS) openmaptiles-tools \ + mbtiles-tools meta-generate "$(MBTILES_LOCAL_FILE)" ./openmaptiles.yaml --auto-minmax --show-ranges .PHONY: start-tileserver start-tileserver: init-dirs @@ -356,7 +508,7 @@ remove-docker-images: .PHONY: clean-unnecessary-docker clean-unnecessary-docker: @echo "Deleting unnecessary container(s)..." - @docker ps -a --filter "status=exited" | $(XARGS) docker rm + @docker ps -a -q --filter "status=exited" | $(XARGS) docker rm @echo "Deleting unnecessary image(s)..." @docker images | grep \ | awk -F" " '{print $$3}' | $(XARGS) docker rmi diff --git a/QUICKSTART.md b/QUICKSTART.md index 7947d2c..c692fdb 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -384,20 +384,17 @@ and the generated maps are going to be available in webbrowser on [localhost:808 This is only a quick preview, because your mbtiles only generated to zoom level 7 ! -### Change MIN_ZOOM and MAX_ZOOM +### Set which zooms to generate -modify the settings in the `.env` file, the defaults : -* QUICKSTART_MIN_ZOOM=0 -* QUICKSTART_MAX_ZOOM=7 +modify the settings in the `.env` file, the defaults: +* `MIN_ZOOM=0` +* `MAX_ZOOM=7` -and re-start `./quickstart.sh ` -* the new config file re-generating to here ./data/docker-compose-config.yml -* Known problems: - * If you use same area - then the ./data/docker-compose-config.yml not re-generating, so you have to modify by hand! +Delete the `./data/.dc-config.yml` file, and re-start `./quickstart.sh ` Hints: -* Small increments! Never starts with the MAX_ZOOM = 14 -* The suggested MAX_ZOOM = 14 - use only with small extracts +* Small increments! Never starts with the `MAX_ZOOM = 14` +* The suggested `MAX_ZOOM = 14` - use only with small extracts ### Check other commands diff --git a/README.md b/README.md index 2ebb322..1285b62 100644 --- a/README.md +++ b/README.md @@ -83,10 +83,10 @@ make ``` You can execute the following manual steps (for better understanding) -or use the provided `quickstart.sh` script. +or use the provided `quickstart.sh` script to automatically download and import given area. If area is not given, albania will be imported. ``` -./quickstart.sh +./quickstart.sh ``` ### Prepare the Database @@ -103,10 +103,10 @@ Import external data from [OpenStreetMapData](http://osmdata.openstreetmap.de/), make import-data ``` -[Download OpenStreetMap data extracts](http://download.geofabrik.de/) and store the PBF file in the `./data` directory. +Download OpenStreetMap data extracts from any source like [Geofabrik](http://download.geofabrik.de/), and store the PBF file in the `./data` directory. To use a specific download source, use `download-geofabrik`, `download-bbbike`, or `download-osmfr`, or use `download` to make it auto-pick the area. You can use `area=planet` for the entire OSM dataset (very large). Note that if you have more than one `data/*.osm.pbf` file, every `make` command will always require `area=...` parameter (or you can just `export area=...` first). ```bash -make download-geofabrik area=albania +make download area=albania ``` [Import OpenStreetMap data](https://github.com/openmaptiles/openmaptiles-tools/tree/master/docker/import-osm) with the mapping rules from @@ -135,11 +135,11 @@ make make import-sql ``` -Now you are ready to **generate the vector tiles**. Using environment variables -you can limit the bounding box and zoom levels of what you want to generate (`docker-compose.yml`). +Now you are ready to **generate the vector tiles**. By default, `./.env` specifies the entire planet BBOX for zooms 0-7, but running `generate-dc-config` will analyze the data file and set the `BBOX` param to limit tile generation. It will also modify `MIN_ZOOM` and `MAX_ZOOM` values based on the .env, but can be changed. ``` -make generate-tiles +make generate-dc-config # compute data bbox -- not needed for the whole planet +make generate-tiles # generate tiles ``` ## License diff --git a/docker-compose.yml b/docker-compose.yml index 45db089..e2d4fc7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,14 @@ services: MAKE_DC_VERSION: "2.3" # Allow DIFF_MODE to be overwritten from shell DIFF_MODE: ${DIFF_MODE} + # Imposm configuration file describes how to load updates when enabled + IMPOSM_CONFIG_FILE: ${IMPOSM_CONFIG_FILE} + # Which files to use during import-borders processing + BORDERS_CLEANUP_FILE: ${BORDERS_CLEANUP_FILE} + BORDERS_PBF_FILE: ${BORDERS_PBF_FILE} + BORDERS_CSV_FILE: ${BORDERS_CSV_FILE} + # Control import-sql processes + MAX_PARALLEL_PSQL: ${MAX_PARALLEL_PSQL} networks: - postgres_conn volumes: @@ -54,6 +62,9 @@ services: networks: - postgres_conn env_file: .env + environment: + FILTER_MAPNIK_OUTPUT: ${FILTER_MAPNIK_OUTPUT} + MBTILES_NAME: ${MBTILES_FILE} generate-vectortiles: image: "openmaptiles/generate-vectortiles:${TOOLS_VERSION}" @@ -64,10 +75,11 @@ services: - postgres_conn env_file: .env environment: + FILTER_MAPNIK_OUTPUT: ${FILTER_MAPNIK_OUTPUT} + MBTILES_NAME: ${MBTILES_FILE} BBOX: ${BBOX} MIN_ZOOM: ${MIN_ZOOM} MAX_ZOOM: ${MAX_ZOOM} - FILTER_MAPNIK_OUTPUT: ${FILTER_MAPNIK_OUTPUT} postserve: image: "openmaptiles/openmaptiles-tools:${TOOLS_VERSION}" diff --git a/layers/aerodrome_label/aerodrome_label.yaml b/layers/aerodrome_label/aerodrome_label.yaml index 0a775c0..d165ff6 100644 --- a/layers/aerodrome_label/aerodrome_label.yaml +++ b/layers/aerodrome_label/aerodrome_label.yaml @@ -41,7 +41,7 @@ layer: key_field: osm_id key_field_as_attribute: no srid: 900913 - query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, iata, icao, ele, ele_ft FROM layer_aerodrome_label (!bbox!, z(!scale_denominator!), !pixel_width!)) AS t + query: (SELECT osm_id, geometry, name, name_en, name_de, {name_languages}, class, iata, icao, ele, ele_ft FROM layer_aerodrome_label(!bbox!, z(!scale_denominator!))) AS t schema: - ./update_aerodrome_label_point.sql - ./layer.sql diff --git a/layers/aerodrome_label/layer.sql b/layers/aerodrome_label/layer.sql index 19e9bac..19b8b2a 100644 --- a/layers/aerodrome_label/layer.sql +++ b/layers/aerodrome_label/layer.sql @@ -1,41 +1,43 @@ -- etldoc: layer_aerodrome_label[shape=record fillcolor=lightpink, style="rounded,filled", label="layer_aerodrome_label | z10+" ] ; -CREATE OR REPLACE FUNCTION layer_aerodrome_label( - bbox geometry, - zoom_level integer, - pixel_width numeric) - RETURNS TABLE( - osm_id bigint, - geometry geometry, - name text, - name_en text, - name_de text, - tags hstore, - class text, - iata text, - icao text, - ele int, - ele_ft int) AS +CREATE OR REPLACE FUNCTION layer_aerodrome_label(bbox geometry, + zoom_level integer) + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + tags hstore, + class text, + iata text, + icao text, + ele int, + ele_ft int + ) +AS $$ - -- etldoc: osm_aerodrome_label_point -> layer_aerodrome_label:z10_ - SELECT +SELECT + -- etldoc: osm_aerodrome_label_point -> layer_aerodrome_label:z10_ osm_id, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, tags, CASE - %%FIELD_MAPPING: class %% - ELSE 'other' - END AS class, - NULLIF(iata, '') AS iata, - NULLIF(icao, '') AS icao, - substring(ele from E'^(-?\\d+)(\\D|$)')::int AS ele, - round(substring(ele from E'^(-?\\d+)(\\D|$)')::int*3.2808399)::int AS ele_ft - FROM osm_aerodrome_label_point - WHERE geometry && bbox AND zoom_level >= 10; -$$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; + %%FIELD_MAPPING: class %% + ELSE 'other' + END AS class, + NULLIF(iata, '') AS iata, + NULLIF(icao, '') AS icao, + substring(ele FROM E'^(-?\\d+)(\\D|$)')::int AS ele, + round(substring(ele FROM E'^(-?\\d+)(\\D|$)')::int * 3.2808399)::int AS ele_ft +FROM osm_aerodrome_label_point +WHERE geometry && bbox + AND zoom_level >= 10; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/aerodrome_label/update_aerodrome_label_point.sql b/layers/aerodrome_label/update_aerodrome_label_point.sql index 541d7ba..e730b51 100644 --- a/layers/aerodrome_label/update_aerodrome_label_point.sql +++ b/layers/aerodrome_label/update_aerodrome_label_point.sql @@ -2,15 +2,16 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_aerodrome_label_point; DROP TRIGGER IF EXISTS trigger_refresh ON aerodrome_label.updates; -- etldoc: osm_aerodrome_label_point -> osm_aerodrome_label_point -CREATE OR REPLACE FUNCTION update_aerodrome_label_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_aerodrome_label_point() RETURNS void AS +$$ BEGIN - UPDATE osm_aerodrome_label_point - SET geometry = ST_Centroid(geometry) - WHERE ST_GeometryType(geometry) <> 'ST_Point'; + UPDATE osm_aerodrome_label_point + SET geometry = ST_Centroid(geometry) + WHERE ST_GeometryType(geometry) <> 'ST_Point'; - UPDATE osm_aerodrome_label_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_aerodrome_label_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; @@ -20,32 +21,40 @@ SELECT update_aerodrome_label_point(); CREATE SCHEMA IF NOT EXISTS aerodrome_label; -CREATE TABLE IF NOT EXISTS aerodrome_label.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION aerodrome_label.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS aerodrome_label.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION aerodrome_label.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO aerodrome_label.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO aerodrome_label.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION aerodrome_label.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh aerodrome_label'; PERFORM update_aerodrome_label_point(); + -- noinspection SqlWithoutWhere DELETE FROM aerodrome_label.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_aerodrome_label_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_aerodrome_label_point FOR EACH STATEMENT - EXECUTE PROCEDURE aerodrome_label.flag(); +EXECUTE PROCEDURE aerodrome_label.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON aerodrome_label.updates + AFTER INSERT + ON aerodrome_label.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE aerodrome_label.refresh(); +EXECUTE PROCEDURE aerodrome_label.refresh(); diff --git a/layers/aeroway/layer.sql b/layers/aeroway/layer.sql index 1116c67..93f03fc 100644 --- a/layers/aeroway/layer.sql +++ b/layers/aeroway/layer.sql @@ -2,44 +2,60 @@ -- etldoc: label="layer_aeroway | z10| z11| z12| z13| z14+" ]; CREATE OR REPLACE FUNCTION layer_aeroway(bbox geometry, zoom_level int) -RETURNS TABLE(geometry geometry, class text, ref text) AS $$ - SELECT geometry, aeroway AS class, ref FROM ( - -- etldoc: osm_aeroway_linestring_gen3 -> layer_aeroway:z10 - SELECT geometry, aeroway, ref - FROM osm_aeroway_linestring_gen3 WHERE zoom_level = 10 - UNION ALL - -- etldoc: osm_aeroway_linestring_gen2 -> layer_aeroway:z11 - SELECT geometry, aeroway, ref - FROM osm_aeroway_linestring_gen2 WHERE zoom_level = 11 - UNION ALL - -- etldoc: osm_aeroway_linestring_gen1 -> layer_aeroway:z12 - SELECT geometry, aeroway, ref - FROM osm_aeroway_linestring_gen1 WHERE zoom_level = 12 - UNION ALL - -- etldoc: osm_aeroway_linestring -> layer_aeroway:z13 - -- etldoc: osm_aeroway_linestring -> layer_aeroway:z14_ - SELECT geometry, aeroway, ref - FROM osm_aeroway_linestring WHERE zoom_level >= 13 - UNION ALL - - -- etldoc: osm_aeroway_polygon_gen3 -> layer_aeroway:z10 - -- etldoc: osm_aeroway_polygon_gen3 -> layer_aeroway:z11 - SELECT geometry, aeroway, ref - FROM osm_aeroway_polygon_gen3 WHERE zoom_level BETWEEN 10 AND 11 - UNION ALL - -- etldoc: osm_aeroway_polygon_gen2 -> layer_aeroway:z12 - SELECT geometry, aeroway, ref - FROM osm_aeroway_polygon_gen2 WHERE zoom_level = 12 - UNION ALL - -- etldoc: osm_aeroway_polygon_gen1 -> layer_aeroway:z13 - SELECT geometry, aeroway, ref - FROM osm_aeroway_polygon_gen1 WHERE zoom_level = 13 - UNION ALL - -- etldoc: osm_aeroway_polygon -> layer_aeroway:z14_ - SELECT geometry, aeroway, ref - FROM osm_aeroway_polygon WHERE zoom_level >= 14 - ) AS zoom_levels - WHERE geometry && bbox; + RETURNS TABLE + ( + geometry geometry, + class text, + ref text + ) +AS $$ -LANGUAGE SQL IMMUTABLE -PARALLEL SAFE; +SELECT geometry, aeroway AS class, ref +FROM ( + -- etldoc: osm_aeroway_linestring_gen3 -> layer_aeroway:z10 + SELECT geometry, aeroway, ref + FROM osm_aeroway_linestring_gen3 + WHERE zoom_level = 10 + UNION ALL + -- etldoc: osm_aeroway_linestring_gen2 -> layer_aeroway:z11 + SELECT geometry, aeroway, ref + FROM osm_aeroway_linestring_gen2 + WHERE zoom_level = 11 + UNION ALL + -- etldoc: osm_aeroway_linestring_gen1 -> layer_aeroway:z12 + SELECT geometry, aeroway, ref + FROM osm_aeroway_linestring_gen1 + WHERE zoom_level = 12 + UNION ALL + -- etldoc: osm_aeroway_linestring -> layer_aeroway:z13 + -- etldoc: osm_aeroway_linestring -> layer_aeroway:z14_ + SELECT geometry, aeroway, ref + FROM osm_aeroway_linestring + WHERE zoom_level >= 13 + UNION ALL + + -- etldoc: osm_aeroway_polygon_gen3 -> layer_aeroway:z10 + -- etldoc: osm_aeroway_polygon_gen3 -> layer_aeroway:z11 + SELECT geometry, aeroway, ref + FROM osm_aeroway_polygon_gen3 + WHERE zoom_level BETWEEN 10 AND 11 + UNION ALL + -- etldoc: osm_aeroway_polygon_gen2 -> layer_aeroway:z12 + SELECT geometry, aeroway, ref + FROM osm_aeroway_polygon_gen2 + WHERE zoom_level = 12 + UNION ALL + -- etldoc: osm_aeroway_polygon_gen1 -> layer_aeroway:z13 + SELECT geometry, aeroway, ref + FROM osm_aeroway_polygon_gen1 + WHERE zoom_level = 13 + UNION ALL + -- etldoc: osm_aeroway_polygon -> layer_aeroway:z14_ + SELECT geometry, aeroway, ref + FROM osm_aeroway_polygon + WHERE zoom_level >= 14 + ) AS zoom_levels +WHERE geometry && bbox; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/boundary/boundary.sql b/layers/boundary/boundary.sql index e0705c9..1100759 100644 --- a/layers/boundary/boundary.sql +++ b/layers/boundary/boundary.sql @@ -1,475 +1,633 @@ -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen1 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen1 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen1 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen1 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen1 AS ( - SELECT ST_Simplify(geometry, 10) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 10 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen1 AS +( +SELECT ST_Simplify(geometry, 10) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 10 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen1_idx ON osm_border_linestring_gen1 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen2 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen2 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen2 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen2 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen2 AS ( - SELECT ST_Simplify(geometry, 20) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 10 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen2 AS +( +SELECT ST_Simplify(geometry, 20) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 10 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen2_idx ON osm_border_linestring_gen2 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen3 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen3 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen3 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen3 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen3 AS ( - SELECT ST_Simplify(geometry, 40) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 8 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen3 AS +( +SELECT ST_Simplify(geometry, 40) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 8 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen3_idx ON osm_border_linestring_gen3 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen4 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen4 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen4 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen4 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen4 AS ( - SELECT ST_Simplify(geometry, 80) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 6 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen4 AS +( +SELECT ST_Simplify(geometry, 80) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 6 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen4_idx ON osm_border_linestring_gen4 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen5 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen5 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen5 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen5 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen5 AS ( - SELECT ST_Simplify(geometry, 160) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 6 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen5 AS +( +SELECT ST_Simplify(geometry, 160) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 6 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen5_idx ON osm_border_linestring_gen5 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen6 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen6 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen6 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen6 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen6 AS ( - SELECT ST_Simplify(geometry, 300) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 4 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen6 AS +( +SELECT ST_Simplify(geometry, 300) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 4 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen6_idx ON osm_border_linestring_gen6 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen7 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen7 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen7 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen7 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen7 AS ( - SELECT ST_Simplify(geometry, 600) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 4 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen7 AS +( +SELECT ST_Simplify(geometry, 600) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 4 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen7_idx ON osm_border_linestring_gen7 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen8 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen8 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen8 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen8 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen8 AS ( - SELECT ST_Simplify(geometry, 1200) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 4 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen8 AS +( +SELECT ST_Simplify(geometry, 1200) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 4 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen8_idx ON osm_border_linestring_gen8 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen9 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen9 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen9 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen9 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen9 AS ( - SELECT ST_Simplify(geometry, 2400) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 4 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen9 AS +( +SELECT ST_Simplify(geometry, 2400) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 4 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen9_idx ON osm_border_linestring_gen9 USING gist (geometry); -- This statement can be deleted after the border importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_border_linestring_gen10 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_border_linestring_gen10 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + -- etldoc: osm_border_linestring -> osm_border_linestring_gen10 DROP MATERIALIZED VIEW IF EXISTS osm_border_linestring_gen10 CASCADE; -CREATE MATERIALIZED VIEW osm_border_linestring_gen10 AS ( - SELECT ST_Simplify(geometry, 4800) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime - FROM osm_border_linestring - WHERE admin_level <= 2 -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE MATERIALIZED VIEW osm_border_linestring_gen10 AS +( +SELECT ST_Simplify(geometry, 4800) AS geometry, osm_id, admin_level, dividing_line, disputed, maritime +FROM osm_border_linestring +WHERE admin_level <= 2 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; CREATE INDEX IF NOT EXISTS osm_border_linestring_gen10_idx ON osm_border_linestring_gen10 USING gist (geometry); -CREATE OR REPLACE FUNCTION edit_name(name VARCHAR) RETURNS TEXT AS $$ - SELECT CASE - WHEN POSITION(' at ' in name) > 0 - THEN replace(SUBSTRING(name, POSITION(' at ' in name)+4), ' ', '') - ELSE replace(replace(name,' ',''),'Extentof','') - END; -$$ LANGUAGE SQL IMMUTABLE; +CREATE OR REPLACE FUNCTION edit_name(name varchar) RETURNS text AS +$$ +SELECT CASE + WHEN POSITION(' at ' IN name) > 0 + THEN replace(SUBSTRING(name, POSITION(' at ' IN name) + 4), ' ', '') + ELSE replace(replace(name, ' ', ''), 'Extentof', '') + END; +$$ LANGUAGE SQL IMMUTABLE + -- STRICT + PARALLEL SAFE + ; -- etldoc: ne_110m_admin_0_boundary_lines_land -> boundary_z0 -CREATE OR REPLACE VIEW boundary_z0 AS ( - SELECT geometry, - 2 AS admin_level, - (CASE WHEN featurecla LIKE 'Disputed%' THEN true ELSE false END) AS disputed, - NULL::text AS disputed_name, - NULL::text AS claimed_by, - false AS maritime - FROM ne_110m_admin_0_boundary_lines_land -); +CREATE OR REPLACE VIEW boundary_z0 AS +( +SELECT geometry, + 2 AS admin_level, + (CASE WHEN featurecla LIKE 'Disputed%' THEN TRUE ELSE FALSE END) AS disputed, + NULL::text AS disputed_name, + NULL::text AS claimed_by, + FALSE AS maritime +FROM ne_110m_admin_0_boundary_lines_land + ); -- etldoc: ne_50m_admin_0_boundary_lines_land -> boundary_z1 -- etldoc: ne_50m_admin_1_states_provinces_lines -> boundary_z1 -- etldoc: osm_border_disp_linestring_gen11 -> boundary_z1 -CREATE OR REPLACE VIEW boundary_z1 AS ( - SELECT geometry, - 2 AS admin_level, - (CASE WHEN featurecla LIKE 'Disputed%' THEN true ELSE false END) AS disputed, - NULL AS disputed_name, - NULL AS claimed_by, - false AS maritime - FROM ne_50m_admin_0_boundary_lines_land - UNION ALL - SELECT geometry, - 4 AS admin_level, - false AS disputed, - NULL AS disputed_name, - NULL AS claimed_by, - false AS maritime - FROM ne_50m_admin_1_states_provinces_lines - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen11 -); +CREATE OR REPLACE VIEW boundary_z1 AS +( +SELECT geometry, + 2 AS admin_level, + (CASE WHEN featurecla LIKE 'Disputed%' THEN TRUE ELSE FALSE END) AS disputed, + NULL AS disputed_name, + NULL AS claimed_by, + FALSE AS maritime +FROM ne_50m_admin_0_boundary_lines_land +UNION ALL +SELECT geometry, + 4 AS admin_level, + FALSE AS disputed, + NULL AS disputed_name, + NULL AS claimed_by, + FALSE AS maritime +FROM ne_50m_admin_1_states_provinces_lines +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen11 + ); -- etldoc: ne_50m_admin_0_boundary_lines_land -> boundary_z3 -- etldoc: ne_50m_admin_1_states_provinces_lines -> boundary_z3 -- etldoc: osm_border_disp_linestring_gen11 -> boundary_z3 -CREATE OR REPLACE VIEW boundary_z3 AS ( - SELECT geometry, - 2 AS admin_level, - (CASE WHEN featurecla LIKE 'Disputed%' THEN true ELSE false END) AS disputed, - NULL AS disputed_name, - NULL AS claimed_by, - false AS maritime - FROM ne_50m_admin_0_boundary_lines_land - UNION ALL - SELECT geometry, - 4 AS admin_level, - false AS disputed, - NULL AS disputed_name, - NULL AS claimed_by, - false AS maritime - FROM ne_50m_admin_1_states_provinces_lines - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen11 -); +CREATE OR REPLACE VIEW boundary_z3 AS +( +SELECT geometry, + 2 AS admin_level, + (CASE WHEN featurecla LIKE 'Disputed%' THEN TRUE ELSE FALSE END) AS disputed, + NULL AS disputed_name, + NULL AS claimed_by, + FALSE AS maritime +FROM ne_50m_admin_0_boundary_lines_land +UNION ALL +SELECT geometry, + 4 AS admin_level, + FALSE AS disputed, + NULL AS disputed_name, + NULL AS claimed_by, + FALSE AS maritime +FROM ne_50m_admin_1_states_provinces_lines +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen11 + ); -- etldoc: ne_10m_admin_0_boundary_lines_land -> boundary_z4 -- etldoc: ne_10m_admin_1_states_provinces_lines -> boundary_z4 -- etldoc: osm_border_linestring_gen10 -> boundary_z4 -- etldoc: osm_border_disp_linestring_gen10 -> boundary_z4 -CREATE OR REPLACE VIEW boundary_z4 AS ( - SELECT geometry, - 2 AS admin_level, - (CASE WHEN featurecla LIKE 'Disputed%' THEN true ELSE false END) AS disputed, - NULL AS disputed_name, - NULL AS claimed_by, - false AS maritime - FROM ne_10m_admin_0_boundary_lines_land - WHERE featurecla <> 'Lease limit' - UNION ALL - SELECT geometry, - 4 AS admin_level, - false AS disputed, - NULL AS disputed_name, - NULL AS claimed_by, - false AS maritime - FROM ne_10m_admin_1_states_provinces_lines - WHERE min_zoom <= 5 - UNION ALL - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen10 - WHERE maritime=true AND admin_level <= 2 - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen10 -); +CREATE OR REPLACE VIEW boundary_z4 AS +( +SELECT geometry, + 2 AS admin_level, + (CASE WHEN featurecla LIKE 'Disputed%' THEN TRUE ELSE FALSE END) AS disputed, + NULL AS disputed_name, + NULL AS claimed_by, + FALSE AS maritime +FROM ne_10m_admin_0_boundary_lines_land +WHERE featurecla <> 'Lease limit' +UNION ALL +SELECT geometry, + 4 AS admin_level, + FALSE AS disputed, + NULL AS disputed_name, + NULL AS claimed_by, + FALSE AS maritime +FROM ne_10m_admin_1_states_provinces_lines +WHERE min_zoom <= 5 +UNION ALL +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen10 +WHERE maritime = TRUE + AND admin_level <= 2 +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen10 + ); -- etldoc: osm_border_linestring_gen9 -> boundary_z5 -- etldoc: osm_border_disp_linestring_gen9 -> boundary_z5 -CREATE OR REPLACE VIEW boundary_z5 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen9 - WHERE admin_level <= 4 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen9) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen9 -); +CREATE OR REPLACE VIEW boundary_z5 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen9 +WHERE admin_level <= 4 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen9) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen9 + ); -- etldoc: osm_border_linestring_gen8 -> boundary_z6 -- etldoc: osm_border_disp_linestring_gen8 -> boundary_z6 -CREATE OR REPLACE VIEW boundary_z6 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen8 - WHERE admin_level <= 4 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen8) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen8 -); +CREATE OR REPLACE VIEW boundary_z6 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen8 +WHERE admin_level <= 4 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen8) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen8 + ); -- etldoc: osm_border_linestring_gen7 -> boundary_z7 -- etldoc: osm_border_disp_linestring_gen7 -> boundary_z7 -CREATE OR REPLACE VIEW boundary_z7 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen7 - WHERE admin_level <= 6 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen7) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen7 -); +CREATE OR REPLACE VIEW boundary_z7 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen7 +WHERE admin_level <= 6 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen7) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen7 + ); -- etldoc: osm_border_linestring_gen6 -> boundary_z8 -- etldoc: osm_border_disp_linestring_gen6 -> boundary_z8 -CREATE OR REPLACE VIEW boundary_z8 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen6 - WHERE admin_level <= 6 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen6) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen6 -); +CREATE OR REPLACE VIEW boundary_z8 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen6 +WHERE admin_level <= 6 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen6) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen6 + ); -- etldoc: osm_border_linestring_gen5 -> boundary_z9 -- etldoc: osm_border_disp_linestring_gen5 -> boundary_z9 -CREATE OR REPLACE VIEW boundary_z9 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen5 - WHERE admin_level <= 6 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen5) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen5 -); +CREATE OR REPLACE VIEW boundary_z9 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen5 +WHERE admin_level <= 6 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen5) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen5 + ); -- etldoc: osm_border_linestring_gen4 -> boundary_z10 -- etldoc: osm_border_disp_linestring_gen4 -> boundary_z10 -CREATE OR REPLACE VIEW boundary_z10 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen4 - WHERE admin_level <= 6 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen4) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen4 -); +CREATE OR REPLACE VIEW boundary_z10 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen4 +WHERE admin_level <= 6 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen4) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen4 + ); -- etldoc: osm_border_linestring_gen3 -> boundary_z11 -- etldoc: osm_border_disp_linestring_gen3 -> boundary_z11 -CREATE OR REPLACE VIEW boundary_z11 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen3 - WHERE admin_level <= 8 - AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen3) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen3 -); +CREATE OR REPLACE VIEW boundary_z11 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen3 +WHERE admin_level <= 8 + AND osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen3) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen3 + ); -- etldoc: osm_border_linestring_gen2 -> boundary_z12 -- etldoc: osm_border_disp_linestring_gen2 -> boundary_z12 -CREATE OR REPLACE VIEW boundary_z12 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen2 - WHERE osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen2) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen2 -); +CREATE OR REPLACE VIEW boundary_z12 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen2 +WHERE osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen2) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen2 + ); -- etldoc: osm_border_linestring_gen1 -> boundary_z13 -- etldoc: osm_border_disp_linestring_gen1 -> boundary_z13 -CREATE OR REPLACE VIEW boundary_z13 AS ( - SELECT geometry, - admin_level, - disputed, - NULL AS disputed_name, - NULL AS claimed_by, - maritime - FROM osm_border_linestring_gen1 - WHERE osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen1) - UNION ALL - SELECT geometry, - admin_level, - true AS disputed, - edit_name(name) AS disputed_name, - claimed_by, - maritime - FROM osm_border_disp_linestring_gen1 -); +CREATE OR REPLACE VIEW boundary_z13 AS +( +SELECT geometry, + admin_level, + disputed, + NULL AS disputed_name, + NULL AS claimed_by, + maritime +FROM osm_border_linestring_gen1 +WHERE osm_id NOT IN (SELECT DISTINCT osm_id FROM osm_border_disp_linestring_gen1) +UNION ALL +SELECT geometry, + admin_level, + TRUE AS disputed, + edit_name(name) AS disputed_name, + claimed_by, + maritime +FROM osm_border_disp_linestring_gen1 + ); -- etldoc: layer_boundary[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label=" layer_boundary | z0 | z1_2 | z3 | z4 | z5 | z6 | z7 | z8 | z9 | z10 | z11 | z12| z13+"] -CREATE OR REPLACE FUNCTION layer_boundary (bbox geometry, zoom_level int) -RETURNS TABLE(geometry geometry, admin_level int, disputed int, disputed_name text, claimed_by text, maritime int) AS $$ - SELECT geometry, admin_level, disputed::int, disputed_name, claimed_by, maritime::int FROM ( - -- etldoc: boundary_z0 -> layer_boundary:z0 - SELECT * FROM boundary_z0 WHERE geometry && bbox AND zoom_level = 0 - UNION ALL - -- etldoc: boundary_z1 -> layer_boundary:z1_2 - SELECT * FROM boundary_z1 WHERE geometry && bbox AND zoom_level BETWEEN 1 AND 2 - UNION ALL - -- etldoc: boundary_z3 -> layer_boundary:z3 - SELECT * FROM boundary_z3 WHERE geometry && bbox AND zoom_level = 3 - UNION ALL - -- etldoc: boundary_z4 -> layer_boundary:z4 - SELECT * FROM boundary_z4 WHERE geometry && bbox AND zoom_level = 4 - UNION ALL - -- etldoc: boundary_z5 -> layer_boundary:z5 - SELECT * FROM boundary_z5 WHERE geometry && bbox AND zoom_level = 5 - UNION ALL - -- etldoc: boundary_z6 -> layer_boundary:z6 - SELECT * FROM boundary_z6 WHERE geometry && bbox AND zoom_level = 6 - UNION ALL - -- etldoc: boundary_z7 -> layer_boundary:z7 - SELECT * FROM boundary_z7 WHERE geometry && bbox AND zoom_level = 7 - UNION ALL - -- etldoc: boundary_z8 -> layer_boundary:z8 - SELECT * FROM boundary_z8 WHERE geometry && bbox AND zoom_level = 8 - UNION ALL - -- etldoc: boundary_z9 -> layer_boundary:z9 - SELECT * FROM boundary_z9 WHERE geometry && bbox AND zoom_level = 9 - UNION ALL - -- etldoc: boundary_z10 -> layer_boundary:z10 - SELECT * FROM boundary_z10 WHERE geometry && bbox AND zoom_level = 10 - UNION ALL - -- etldoc: boundary_z11 -> layer_boundary:z11 - SELECT * FROM boundary_z11 WHERE geometry && bbox AND zoom_level = 11 - UNION ALL - -- etldoc: boundary_z12 -> layer_boundary:z12 - SELECT * FROM boundary_z12 WHERE geometry && bbox AND zoom_level = 12 - UNION ALL - -- etldoc: boundary_z13 -> layer_boundary:z13 - SELECT * FROM boundary_z13 WHERE geometry && bbox AND zoom_level >= 13 - ) AS zoom_levels; +CREATE OR REPLACE FUNCTION layer_boundary(bbox geometry, zoom_level int) + RETURNS TABLE + ( + geometry geometry, + admin_level int, + disputed int, + disputed_name text, + claimed_by text, + maritime int + ) +AS $$ -LANGUAGE SQL IMMUTABLE -PARALLEL SAFE; +SELECT geometry, admin_level, disputed::int, disputed_name, claimed_by, maritime::int +FROM ( + -- etldoc: boundary_z0 -> layer_boundary:z0 + SELECT * + FROM boundary_z0 + WHERE geometry && bbox + AND zoom_level = 0 + UNION ALL + -- etldoc: boundary_z1 -> layer_boundary:z1_2 + SELECT * + FROM boundary_z1 + WHERE geometry && bbox + AND zoom_level BETWEEN 1 AND 2 + UNION ALL + -- etldoc: boundary_z3 -> layer_boundary:z3 + SELECT * + FROM boundary_z3 + WHERE geometry && bbox + AND zoom_level = 3 + UNION ALL + -- etldoc: boundary_z4 -> layer_boundary:z4 + SELECT * + FROM boundary_z4 + WHERE geometry && bbox + AND zoom_level = 4 + UNION ALL + -- etldoc: boundary_z5 -> layer_boundary:z5 + SELECT * + FROM boundary_z5 + WHERE geometry && bbox + AND zoom_level = 5 + UNION ALL + -- etldoc: boundary_z6 -> layer_boundary:z6 + SELECT * + FROM boundary_z6 + WHERE geometry && bbox + AND zoom_level = 6 + UNION ALL + -- etldoc: boundary_z7 -> layer_boundary:z7 + SELECT * + FROM boundary_z7 + WHERE geometry && bbox + AND zoom_level = 7 + UNION ALL + -- etldoc: boundary_z8 -> layer_boundary:z8 + SELECT * + FROM boundary_z8 + WHERE geometry && bbox + AND zoom_level = 8 + UNION ALL + -- etldoc: boundary_z9 -> layer_boundary:z9 + SELECT * + FROM boundary_z9 + WHERE geometry && bbox + AND zoom_level = 9 + UNION ALL + -- etldoc: boundary_z10 -> layer_boundary:z10 + SELECT * + FROM boundary_z10 + WHERE geometry && bbox + AND zoom_level = 10 + UNION ALL + -- etldoc: boundary_z11 -> layer_boundary:z11 + SELECT * + FROM boundary_z11 + WHERE geometry && bbox + AND zoom_level = 11 + UNION ALL + -- etldoc: boundary_z12 -> layer_boundary:z12 + SELECT * + FROM boundary_z12 + WHERE geometry && bbox + AND zoom_level = 12 + UNION ALL + -- etldoc: boundary_z13 -> layer_boundary:z13 + SELECT * + FROM boundary_z13 + WHERE geometry && bbox + AND zoom_level >= 13 + ) AS zoom_levels; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/boundary/mapping.yaml b/layers/boundary/mapping.yaml index aacb1b5..0acc08a 100644 --- a/layers/boundary/mapping.yaml +++ b/layers/boundary/mapping.yaml @@ -110,4 +110,3 @@ tables: #admin_level: ['2'] admin_level: [__any__] claimed_by: [__any__] - diff --git a/layers/building/building.sql b/layers/building/building.sql index 5a99017..47b2c51 100644 --- a/layers/building/building.sql +++ b/layers/building/building.sql @@ -1,95 +1,120 @@ -- etldoc: layer_building[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_building | z13 | z14+ " ] ; -CREATE INDEX IF NOT EXISTS osm_building_relation_building_idx ON osm_building_relation(building) WHERE building = '' AND ST_GeometryType(geometry) = 'ST_Polygon'; -CREATE INDEX IF NOT EXISTS osm_building_relation_member_idx ON osm_building_relation(member) WHERE role = 'outline'; +CREATE INDEX IF NOT EXISTS osm_building_relation_building_idx ON osm_building_relation (building) WHERE building = '' AND ST_GeometryType(geometry) = 'ST_Polygon'; +CREATE INDEX IF NOT EXISTS osm_building_relation_member_idx ON osm_building_relation (member) WHERE role = 'outline'; -CREATE OR REPLACE VIEW osm_all_buildings AS ( - -- etldoc: osm_building_relation -> layer_building:z14_ - -- Buildings built from relations - SELECT member AS osm_id, geometry, - COALESCE(CleanNumeric(height), CleanNumeric(buildingheight)) as height, - COALESCE(CleanNumeric(min_height), CleanNumeric(buildingmin_height)) as min_height, - COALESCE(CleanNumeric(levels), CleanNumeric(buildinglevels)) as levels, - COALESCE(CleanNumeric(min_level), CleanNumeric(buildingmin_level)) as min_level, - nullif(material, '') AS material, - nullif(colour, '') AS colour, - FALSE as hide_3d - FROM - osm_building_relation WHERE building = '' AND ST_GeometryType(geometry) = 'ST_Polygon' - UNION ALL +CREATE OR REPLACE VIEW osm_all_buildings AS +( +SELECT + -- etldoc: osm_building_relation -> layer_building:z14_ + -- Buildings built from relations + member AS osm_id, + geometry, + COALESCE(CleanNumeric(height), CleanNumeric(buildingheight)) AS height, + COALESCE(CleanNumeric(min_height), CleanNumeric(buildingmin_height)) AS min_height, + COALESCE(CleanNumeric(levels), CleanNumeric(buildinglevels)) AS levels, + COALESCE(CleanNumeric(min_level), CleanNumeric(buildingmin_level)) AS min_level, + nullif(material, '') AS material, + nullif(colour, '') AS colour, + FALSE AS hide_3d +FROM osm_building_relation +WHERE building = '' + AND ST_GeometryType(geometry) = 'ST_Polygon' +UNION ALL - -- etldoc: osm_building_polygon -> layer_building:z14_ - -- Standalone buildings - SELECT obp.osm_id, obp.geometry, - COALESCE(CleanNumeric(obp.height), CleanNumeric(obp.buildingheight)) as height, - COALESCE(CleanNumeric(obp.min_height), CleanNumeric(obp.buildingmin_height)) as min_height, - COALESCE(CleanNumeric(obp.levels), CleanNumeric(obp.buildinglevels)) as levels, - COALESCE(CleanNumeric(obp.min_level), CleanNumeric(obp.buildingmin_level)) as min_level, - nullif(obp.material, '') AS material, - nullif(obp.colour, '') AS colour, - obr.role IS NOT NULL AS hide_3d - FROM - osm_building_polygon obp - LEFT JOIN osm_building_relation obr ON - obp.osm_id >= 0 AND - obr.member = obp.osm_id AND - obr.role = 'outline' - WHERE ST_GeometryType(obp.geometry) IN ('ST_Polygon', 'ST_MultiPolygon') -); +SELECT + -- etldoc: osm_building_polygon -> layer_building:z14_ + -- Standalone buildings + obp.osm_id, + obp.geometry, + COALESCE(CleanNumeric(obp.height), CleanNumeric(obp.buildingheight)) AS height, + COALESCE(CleanNumeric(obp.min_height), CleanNumeric(obp.buildingmin_height)) AS min_height, + COALESCE(CleanNumeric(obp.levels), CleanNumeric(obp.buildinglevels)) AS levels, + COALESCE(CleanNumeric(obp.min_level), CleanNumeric(obp.buildingmin_level)) AS min_level, + nullif(obp.material, '') AS material, + nullif(obp.colour, '') AS colour, + obr.role IS NOT NULL AS hide_3d +FROM osm_building_polygon obp + LEFT JOIN osm_building_relation obr ON + obp.osm_id >= 0 AND + obr.member = obp.osm_id AND + obr.role = 'outline' +WHERE ST_GeometryType(obp.geometry) IN ('ST_Polygon', 'ST_MultiPolygon') + ); CREATE OR REPLACE FUNCTION layer_building(bbox geometry, zoom_level int) -RETURNS TABLE(geometry geometry, osm_id bigint, render_height int, render_min_height int, colour text, hide_3d boolean) AS $$ - SELECT geometry, osm_id, render_height, render_min_height, + RETURNS TABLE + ( + geometry geometry, + osm_id bigint, + render_height int, + render_min_height int, + colour text, + hide_3d boolean + ) +AS +$$ +SELECT geometry, + osm_id, + render_height, + render_min_height, COALESCE(colour, CASE material -- Ordered by count from taginfo - WHEN 'cement_block' THEN '#6a7880' - WHEN 'brick' THEN '#bd8161' - WHEN 'plaster' THEN '#dadbdb' - WHEN 'wood' THEN '#d48741' - WHEN 'concrete' THEN '#d3c2b0' - WHEN 'metal' THEN '#b7b1a6' - WHEN 'stone' THEN '#b4a995' - WHEN 'mud' THEN '#9d8b75' - WHEN 'steel' THEN '#b7b1a6' -- same as metal - WHEN 'glass' THEN '#5a81a0' - WHEN 'traditional' THEN '#bd8161' -- same as brick - WHEN 'masonry' THEN '#bd8161' -- same as brick - WHEN 'Brick' THEN '#bd8161' -- same as brick - WHEN 'tin' THEN '#b7b1a6' -- same as metal - WHEN 'timber_framing' THEN '#b3b0a9' - WHEN 'sandstone' THEN '#b4a995' -- same as stone - WHEN 'clay' THEN '#9d8b75' -- same as mud - END) AS colour, - CASE WHEN hide_3d THEN TRUE END AS hide_3d - FROM ( - -- etldoc: osm_building_polygon_gen1 -> layer_building:z13 - SELECT - osm_id, geometry, - NULL::int AS render_height, NULL::int AS render_min_height, - NULL::text AS material, NULL::text AS colour, - FALSE AS hide_3d - FROM osm_building_polygon_gen1 - WHERE zoom_level = 13 AND geometry && bbox - UNION ALL - -- etldoc: osm_building_polygon -> layer_building:z14_ - SELECT DISTINCT ON (osm_id) - osm_id, geometry, - ceil(COALESCE(height, levels*3.66, 5))::int AS render_height, - floor(COALESCE(min_height, min_level*3.66, 0))::int AS render_min_height, - material, - colour, - hide_3d - FROM osm_all_buildings - WHERE - (levels IS NULL OR levels < 1000) AND - (min_level IS NULL OR min_level < 1000) AND - (height IS NULL OR height < 3000) AND - (min_height IS NULL OR min_height < 3000) AND - zoom_level >= 14 AND geometry && bbox - ) AS zoom_levels - ORDER BY render_height ASC, ST_YMin(geometry) DESC; -$$ -LANGUAGE SQL IMMUTABLE; + WHEN 'cement_block' THEN '#6a7880' + WHEN 'brick' THEN '#bd8161' + WHEN 'plaster' THEN '#dadbdb' + WHEN 'wood' THEN '#d48741' + WHEN 'concrete' THEN '#d3c2b0' + WHEN 'metal' THEN '#b7b1a6' + WHEN 'stone' THEN '#b4a995' + WHEN 'mud' THEN '#9d8b75' + WHEN 'steel' THEN '#b7b1a6' -- same as metal + WHEN 'glass' THEN '#5a81a0' + WHEN 'traditional' THEN '#bd8161' -- same as brick + WHEN 'masonry' THEN '#bd8161' -- same as brick + WHEN 'Brick' THEN '#bd8161' -- same as brick + WHEN 'tin' THEN '#b7b1a6' -- same as metal + WHEN 'timber_framing' THEN '#b3b0a9' + WHEN 'sandstone' THEN '#b4a995' -- same as stone + WHEN 'clay' THEN '#9d8b75' -- same as mud + END) AS colour, + CASE WHEN hide_3d THEN TRUE END AS hide_3d +FROM ( + SELECT + -- etldoc: osm_building_block_gen1 -> layer_building:z13 + osm_id, + geometry, + NULL::int AS render_height, + NULL::int AS render_min_height, + NULL::text AS material, + NULL::text AS colour, + FALSE AS hide_3d + FROM osm_building_block_gen1 + WHERE zoom_level = 13 + AND geometry && bbox + UNION ALL + SELECT + -- etldoc: osm_building_polygon -> layer_building:z14_ + DISTINCT ON (osm_id) osm_id, + geometry, + ceil(COALESCE(height, levels * 3.66, 5))::int AS render_height, + floor(COALESCE(min_height, min_level * 3.66, 0))::int AS render_min_height, + material, + colour, + hide_3d + FROM osm_all_buildings + WHERE (levels IS NULL OR levels < 1000) + AND (min_level IS NULL OR min_level < 1000) + AND (height IS NULL OR height < 3000) + AND (min_height IS NULL OR min_height < 3000) + AND zoom_level >= 14 + AND geometry && bbox + ) AS zoom_levels +ORDER BY render_height ASC, ST_YMin(geometry) DESC; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE + ; -- not handled: where a building outline covers building parts diff --git a/layers/building/building.yaml b/layers/building/building.yaml index 1bf360b..ea2bc67 100644 --- a/layers/building/building.yaml +++ b/layers/building/building.yaml @@ -20,7 +20,8 @@ layer: hide_3d: | If True, building (part) should not be rendered in 3D. Currently, [building outlines](https://wiki.openstreetmap.org/wiki/Simple_3D_buildings) are marked as hide_3d. schema: + - ./update_building.sql - ./building.sql datasources: - type: imposm3 - mapping_file: ./mapping.yaml + mapping_file: ./mapping.yaml \ No newline at end of file diff --git a/layers/building/etl_diagram.png b/layers/building/etl_diagram.png index 53f5f04..c77cd48 100644 Binary files a/layers/building/etl_diagram.png and b/layers/building/etl_diagram.png differ diff --git a/layers/building/mapping.yaml b/layers/building/mapping.yaml index ce72b97..858899b 100644 --- a/layers/building/mapping.yaml +++ b/layers/building/mapping.yaml @@ -1,9 +1,9 @@ -generalized_tables: - # etldoc: imposm3 -> osm_building_polygon_gen1 - building_polygon_gen1: - source: building_polygon - sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry) - tolerance: ZRES14 +#generalized_tables: +# # etldoc: imposm3 -> osm_building_polygon_gen1 +# building_polygon_gen1: +# source: building_polygon +# sql_filter: area>power(ZRES12,2) AND ST_IsValid(geometry) +# tolerance: ZRES14 tables: # etldoc: imposm3 -> osm_building_polygon @@ -157,4 +157,4 @@ tables: type: member_type mapping: type: [building] - type: relation_member + type: relation_member \ No newline at end of file diff --git a/layers/building/update_building.sql b/layers/building/update_building.sql new file mode 100644 index 0000000..5c15ae8 --- /dev/null +++ b/layers/building/update_building.sql @@ -0,0 +1,125 @@ +DROP TRIGGER IF EXISTS trigger_refresh ON buildings.updates; +DROP TRIGGER IF EXISTS trigger_flag ON osm_building_polygon; + +--creating aggregated building blocks with removed small polygons and small +--holes. Aggregated polygons are simplified. + +--function returning recordset for matview +--returning recordset of buildings aggregates by zres 14, with removed small +--holes and with removed small buildings/blocks +-- + +CREATE OR REPLACE FUNCTION osm_building_block_gen1() + RETURNS table + ( + osm_id bigint, + geometry geometry + ) +AS +$$ +DECLARE + zres14 float := Zres(14); + zres12 float := Zres(12); +BEGIN + FOR osm_id, geometry IN + WITH dta AS ( -- CTE is used because of optimization + SELECT o.osm_id, o.geometry, ST_ClusterDBSCAN(o.geometry, eps := zres14, minpoints := 1) OVER () cid + FROM osm_building_polygon o + ) + SELECT (array_agg(dta.osm_id))[1] osm_id, + ST_Buffer(ST_MemUnion(ST_Buffer(dta.geometry, zres14, 'join=mitre')), -zres14, 'join=mitre') geometry + FROM dta + GROUP BY cid + + LOOP + -- removing holes smaller than + IF ST_NumInteriorRings(geometry) > 0 THEN -- only from geometries wih holes + geometry := ( + -- there are some multi-geometries in this layer + SELECT ST_Collect(gn) + FROM ( + -- in some cases are "holes" NULL, because all holes are smaller than + SELECT COALESCE( + -- exterior ring + ST_MakePolygon(ST_ExteriorRing(dmp.geom), holes), + ST_MakePolygon(ST_ExteriorRing(dmp.geom)) + ) gn + + FROM ST_Dump(geometry) dmp, -- 1 dump polygons + LATERAL ( + SELECT array_agg(ST_Boundary(rg.geom)) holes -- 2 create array + FROM ST_DumpRings(dmp.geom) rg -- 3 from rings + WHERE rg.path[1] > 0 -- 5 except inner ring + AND ST_Area(rg.geom) >= power(zres12, 2) -- 4 bigger than + ) holes + ) new_geom + ); + END IF; + + IF ST_Area(geometry) < power(zres12, 2) THEN + CONTINUE; + END IF; + + -- simplify + geometry := ST_SimplifyPreserveTopology(geometry, zres14::float); + + RETURN NEXT; + END LOOP; +END; +$$ LANGUAGE plpgsql STABLE + STRICT + PARALLEL SAFE; + + +DROP MATERIALIZED VIEW IF EXISTS osm_building_block_gen1; + +CREATE MATERIALIZED VIEW osm_building_block_gen1 AS +SELECT * +FROM osm_building_block_gen1(); + +CREATE INDEX ON osm_building_block_gen1 USING gist (geometry); +CREATE UNIQUE INDEX ON osm_building_block_gen1 USING btree (osm_id); + + +-- Handle updates + +CREATE SCHEMA IF NOT EXISTS buildings; + +CREATE TABLE IF NOT EXISTS buildings.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); + +CREATE OR REPLACE FUNCTION buildings.flag() RETURNS trigger AS +$$ +BEGIN + INSERT INTO buildings.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION buildings.refresh() RETURNS trigger AS +$$ +BEGIN + RAISE LOG 'Refresh buildings block'; + REFRESH MATERIALIZED VIEW osm_building_block_gen1; + -- noinspection SqlWithoutWhere + DELETE FROM buildings.updates; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER trigger_flag + AFTER INSERT OR UPDATE OR DELETE + ON osm_building_polygon + FOR EACH STATEMENT +EXECUTE PROCEDURE buildings.flag(); + +CREATE CONSTRAINT TRIGGER trigger_refresh + AFTER INSERT + ON buildings.updates + INITIALLY DEFERRED + FOR EACH ROW +EXECUTE PROCEDURE buildings.refresh(); \ No newline at end of file diff --git a/layers/housenumber/housenumber_centroid.sql b/layers/housenumber/housenumber_centroid.sql index a0722bd..fad1f3d 100644 --- a/layers/housenumber/housenumber_centroid.sql +++ b/layers/housenumber/housenumber_centroid.sql @@ -2,15 +2,17 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_housenumber_point; DROP TRIGGER IF EXISTS trigger_refresh ON housenumber.updates; -- etldoc: osm_housenumber_point -> osm_housenumber_point -CREATE OR REPLACE FUNCTION convert_housenumber_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION convert_housenumber_point() RETURNS void AS +$$ BEGIN - UPDATE osm_housenumber_point - SET geometry = - CASE WHEN ST_NPoints(ST_ConvexHull(geometry))=ST_NPoints(geometry) - THEN ST_Centroid(geometry) - ELSE ST_PointOnSurface(geometry) - END - WHERE ST_GeometryType(geometry) <> 'ST_Point'; + UPDATE osm_housenumber_point + SET geometry = + CASE + WHEN ST_NPoints(ST_ConvexHull(geometry)) = ST_NPoints(geometry) + THEN ST_Centroid(geometry) + ELSE ST_PointOnSurface(geometry) + END + WHERE ST_GeometryType(geometry) <> 'ST_Point'; END; $$ LANGUAGE plpgsql; @@ -20,32 +22,40 @@ SELECT convert_housenumber_point(); CREATE SCHEMA IF NOT EXISTS housenumber; -CREATE TABLE IF NOT EXISTS housenumber.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION housenumber.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS housenumber.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION housenumber.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO housenumber.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO housenumber.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION housenumber.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh housenumber'; PERFORM convert_housenumber_point(); + -- noinspection SqlWithoutWhere DELETE FROM housenumber.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_housenumber_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_housenumber_point FOR EACH STATEMENT - EXECUTE PROCEDURE housenumber.flag(); +EXECUTE PROCEDURE housenumber.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON housenumber.updates + AFTER INSERT + ON housenumber.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE housenumber.refresh(); +EXECUTE PROCEDURE housenumber.refresh(); diff --git a/layers/housenumber/layer.sql b/layers/housenumber/layer.sql index 01f2649..84cb4d8 100644 --- a/layers/housenumber/layer.sql +++ b/layers/housenumber/layer.sql @@ -1,12 +1,23 @@ - -- etldoc: layer_housenumber[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_housenumber | z14+" ] ; CREATE OR REPLACE FUNCTION layer_housenumber(bbox geometry, zoom_level integer) -RETURNS TABLE(osm_id bigint, geometry geometry, housenumber text) AS $$ - -- etldoc: osm_housenumber_point -> layer_housenumber:z14_ - SELECT osm_id, geometry, housenumber FROM osm_housenumber_point - WHERE zoom_level >= 14 AND geometry && bbox; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + housenumber text + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT + -- etldoc: osm_housenumber_point -> layer_housenumber:z14_ + osm_id, + geometry, + housenumber +FROM osm_housenumber_point +WHERE zoom_level >= 14 + AND geometry && bbox; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/landcover/landcover.sql b/layers/landcover/landcover.sql index 3fb62b6..35e4d59 100644 --- a/layers/landcover/landcover.sql +++ b/layers/landcover/landcover.sql @@ -9,127 +9,183 @@ --); --CREATE INDEX IF NOT EXISTS landcover_grouped_gen2_geometry_idx ON landcover_grouped_gen2 USING gist(geometry); -CREATE OR REPLACE FUNCTION landcover_class(subclass VARCHAR) RETURNS TEXT AS $$ - SELECT CASE - %%FIELD_MAPPING: class %% - END; +CREATE OR REPLACE FUNCTION landcover_class(subclass varchar) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT CASE + %%FIELD_MAPPING: class %% + END; +$$ LANGUAGE SQL IMMUTABLE + -- STRICT + PARALLEL SAFE; -- etldoc: ne_110m_glaciated_areas -> landcover_z0 -CREATE OR REPLACE VIEW landcover_z0 AS ( - SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass FROM ne_110m_glaciated_areas -); +CREATE OR REPLACE VIEW landcover_z0 AS +( +SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass +FROM ne_110m_glaciated_areas + ); -CREATE OR REPLACE VIEW landcover_z2 AS ( - -- etldoc: ne_50m_glaciated_areas -> landcover_z2 - SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass FROM ne_50m_glaciated_areas - UNION ALL - -- etldoc: ne_50m_antarctic_ice_shelves_polys -> landcover_z2 - SELECT NULL::bigint AS osm_id, geometry, 'ice_shelf'::text AS subclass FROM ne_50m_antarctic_ice_shelves_polys -); +CREATE OR REPLACE VIEW landcover_z2 AS +( +-- etldoc: ne_50m_glaciated_areas -> landcover_z2 +SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass +FROM ne_50m_glaciated_areas +UNION ALL +-- etldoc: ne_50m_antarctic_ice_shelves_polys -> landcover_z2 +SELECT NULL::bigint AS osm_id, geometry, 'ice_shelf'::text AS subclass +FROM ne_50m_antarctic_ice_shelves_polys + ); -CREATE OR REPLACE VIEW landcover_z5 AS ( - -- etldoc: ne_10m_glaciated_areas -> landcover_z5 - SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass FROM ne_10m_glaciated_areas - UNION ALL - -- etldoc: ne_10m_antarctic_ice_shelves_polys -> landcover_z5 - SELECT NULL::bigint AS osm_id, geometry, 'ice_shelf'::text AS subclass FROM ne_10m_antarctic_ice_shelves_polys -); +CREATE OR REPLACE VIEW landcover_z5 AS +( +-- etldoc: ne_10m_glaciated_areas -> landcover_z5 +SELECT NULL::bigint AS osm_id, geometry, 'glacier'::text AS subclass +FROM ne_10m_glaciated_areas +UNION ALL +-- etldoc: ne_10m_antarctic_ice_shelves_polys -> landcover_z5 +SELECT NULL::bigint AS osm_id, geometry, 'ice_shelf'::text AS subclass +FROM ne_10m_antarctic_ice_shelves_polys + ); -CREATE OR REPLACE VIEW landcover_z7 AS ( - -- etldoc: osm_landcover_polygon_gen7 -> landcover_z7 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen7 -); +CREATE OR REPLACE VIEW landcover_z7 AS +( +-- etldoc: osm_landcover_polygon_gen7 -> landcover_z7 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen7 + ); -CREATE OR REPLACE VIEW landcover_z8 AS ( - -- etldoc: osm_landcover_polygon_gen6 -> landcover_z8 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen6 -); +CREATE OR REPLACE VIEW landcover_z8 AS +( +-- etldoc: osm_landcover_polygon_gen6 -> landcover_z8 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen6 + ); -CREATE OR REPLACE VIEW landcover_z9 AS ( - -- etldoc: osm_landcover_polygon_gen5 -> landcover_z9 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen5 -); +CREATE OR REPLACE VIEW landcover_z9 AS +( +-- etldoc: osm_landcover_polygon_gen5 -> landcover_z9 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen5 + ); -CREATE OR REPLACE VIEW landcover_z10 AS ( - -- etldoc: osm_landcover_polygon_gen4 -> landcover_z10 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen4 -); +CREATE OR REPLACE VIEW landcover_z10 AS +( +-- etldoc: osm_landcover_polygon_gen4 -> landcover_z10 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen4 + ); -CREATE OR REPLACE VIEW landcover_z11 AS ( - -- etldoc: osm_landcover_polygon_gen3 -> landcover_z11 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen3 -); +CREATE OR REPLACE VIEW landcover_z11 AS +( +-- etldoc: osm_landcover_polygon_gen3 -> landcover_z11 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen3 + ); -CREATE OR REPLACE VIEW landcover_z12 AS ( - -- etldoc: osm_landcover_polygon_gen2 -> landcover_z12 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen2 -); +CREATE OR REPLACE VIEW landcover_z12 AS +( +-- etldoc: osm_landcover_polygon_gen2 -> landcover_z12 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen2 + ); -CREATE OR REPLACE VIEW landcover_z13 AS ( - -- etldoc: osm_landcover_polygon_gen1 -> landcover_z13 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon_gen1 -); +CREATE OR REPLACE VIEW landcover_z13 AS +( +-- etldoc: osm_landcover_polygon_gen1 -> landcover_z13 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon_gen1 + ); -CREATE OR REPLACE VIEW landcover_z14 AS ( - -- etldoc: osm_landcover_polygon -> landcover_z14 - SELECT osm_id, geometry, subclass FROM osm_landcover_polygon -); +CREATE OR REPLACE VIEW landcover_z14 AS +( +-- etldoc: osm_landcover_polygon -> landcover_z14 +SELECT osm_id, geometry, subclass +FROM osm_landcover_polygon + ); -- etldoc: layer_landcover[shape=record fillcolor=lightpink, style="rounded, filled", label="layer_landcover | z0-z1 | z2-z4 | z5-z6 | z7 | z8 | z9 | z10 | z11 | z12| z13| z14+" ] ; CREATE OR REPLACE FUNCTION layer_landcover(bbox geometry, zoom_level int) -RETURNS TABLE(osm_id bigint, geometry geometry, class text, subclass text) AS $$ - SELECT osm_id, geometry, - landcover_class(subclass) AS class, - subclass - FROM ( - -- etldoc: landcover_z0 -> layer_landcover:z0_1 - SELECT * FROM landcover_z0 - WHERE zoom_level BETWEEN 0 AND 1 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z2 -> layer_landcover:z2_4 - SELECT * FROM landcover_z2 - WHERE zoom_level BETWEEN 2 AND 4 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z5 -> layer_landcover:z5_6 - SELECT * FROM landcover_z5 - WHERE zoom_level BETWEEN 5 AND 6 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z7 -> layer_landcover:z7 - SELECT * - FROM landcover_z7 WHERE zoom_level = 7 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z8 -> layer_landcover:z8 - SELECT * - FROM landcover_z8 WHERE zoom_level = 8 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z9 -> layer_landcover:z9 - SELECT * - FROM landcover_z9 WHERE zoom_level = 9 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z10 -> layer_landcover:z10 - SELECT * - FROM landcover_z10 WHERE zoom_level = 10 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z11 -> layer_landcover:z11 - SELECT * - FROM landcover_z11 WHERE zoom_level = 11 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z12 -> layer_landcover:z12 - SELECT * - FROM landcover_z12 WHERE zoom_level = 12 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z13 -> layer_landcover:z13 - SELECT * - FROM landcover_z13 WHERE zoom_level = 13 AND geometry && bbox - UNION ALL - -- etldoc: landcover_z14 -> layer_landcover:z14_ - SELECT * - FROM landcover_z14 WHERE zoom_level >= 14 AND geometry && bbox - ) AS zoom_levels; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + class text, + subclass text + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT osm_id, + geometry, + landcover_class(subclass) AS class, + subclass +FROM ( + -- etldoc: landcover_z0 -> layer_landcover:z0_1 + SELECT * + FROM landcover_z0 + WHERE zoom_level BETWEEN 0 AND 1 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z2 -> layer_landcover:z2_4 + SELECT * + FROM landcover_z2 + WHERE zoom_level BETWEEN 2 AND 4 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z5 -> layer_landcover:z5_6 + SELECT * + FROM landcover_z5 + WHERE zoom_level BETWEEN 5 AND 6 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z7 -> layer_landcover:z7 + SELECT * + FROM landcover_z7 + WHERE zoom_level = 7 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z8 -> layer_landcover:z8 + SELECT * + FROM landcover_z8 + WHERE zoom_level = 8 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z9 -> layer_landcover:z9 + SELECT * + FROM landcover_z9 + WHERE zoom_level = 9 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z10 -> layer_landcover:z10 + SELECT * + FROM landcover_z10 + WHERE zoom_level = 10 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z11 -> layer_landcover:z11 + SELECT * + FROM landcover_z11 + WHERE zoom_level = 11 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z12 -> layer_landcover:z12 + SELECT * + FROM landcover_z12 + WHERE zoom_level = 12 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z13 -> layer_landcover:z13 + SELECT * + FROM landcover_z13 + WHERE zoom_level = 13 + AND geometry && bbox + UNION ALL + -- etldoc: landcover_z14 -> layer_landcover:z14_ + SELECT * + FROM landcover_z14 + WHERE zoom_level >= 14 + AND geometry && bbox + ) AS zoom_levels; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/landuse/landuse.sql b/layers/landuse/landuse.sql index fb3f06a..a1cae13 100644 --- a/layers/landuse/landuse.sql +++ b/layers/landuse/landuse.sql @@ -1,113 +1,219 @@ -- etldoc: ne_50m_urban_areas -> landuse_z4 -CREATE OR REPLACE VIEW landuse_z4 AS ( - SELECT NULL::bigint AS osm_id, geometry, 'residential'::text AS landuse, NULL::text AS amenity, NULL::text AS leisure, NULL::text AS tourism, NULL::text AS place, NULL::text AS waterway - FROM ne_50m_urban_areas - WHERE scalerank <= 2 -); +CREATE OR REPLACE VIEW landuse_z4 AS +( +SELECT NULL::bigint AS osm_id, + geometry, + 'residential'::text AS landuse, + NULL::text AS amenity, + NULL::text AS leisure, + NULL::text AS tourism, + NULL::text AS place, + NULL::text AS waterway +FROM ne_50m_urban_areas +WHERE scalerank <= 2 + ); -- etldoc: ne_50m_urban_areas -> landuse_z5 -CREATE OR REPLACE VIEW landuse_z5 AS ( - SELECT NULL::bigint AS osm_id, geometry, 'residential'::text AS landuse, NULL::text AS amenity, NULL::text AS leisure, NULL::text AS tourism, NULL::text AS place, NULL::text AS waterway - FROM ne_50m_urban_areas -); +CREATE OR REPLACE VIEW landuse_z5 AS +( +SELECT NULL::bigint AS osm_id, + geometry, + 'residential'::text AS landuse, + NULL::text AS amenity, + NULL::text AS leisure, + NULL::text AS tourism, + NULL::text AS place, + NULL::text AS waterway +FROM ne_50m_urban_areas + ); -- etldoc: osm_landuse_polygon_gen7 -> landuse_z6 -CREATE OR REPLACE VIEW landuse_z6 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen7 -); +CREATE OR REPLACE VIEW landuse_z6 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen7 + ); -- etldoc: osm_landuse_polygon_gen6 -> landuse_z8 -CREATE OR REPLACE VIEW landuse_z8 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen6 -); +CREATE OR REPLACE VIEW landuse_z8 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen6 + ); -- etldoc: osm_landuse_polygon_gen5 -> landuse_z9 -CREATE OR REPLACE VIEW landuse_z9 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen5 -); +CREATE OR REPLACE VIEW landuse_z9 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen5 + ); -- etldoc: osm_landuse_polygon_gen4 -> landuse_z10 -CREATE OR REPLACE VIEW landuse_z10 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen4 -); +CREATE OR REPLACE VIEW landuse_z10 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen4 + ); -- etldoc: osm_landuse_polygon_gen3 -> landuse_z11 -CREATE OR REPLACE VIEW landuse_z11 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen3 -); +CREATE OR REPLACE VIEW landuse_z11 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen3 + ); -- etldoc: osm_landuse_polygon_gen2 -> landuse_z12 -CREATE OR REPLACE VIEW landuse_z12 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen2 -); +CREATE OR REPLACE VIEW landuse_z12 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen2 + ); -- etldoc: osm_landuse_polygon_gen1 -> landuse_z13 -CREATE OR REPLACE VIEW landuse_z13 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon_gen1 -); +CREATE OR REPLACE VIEW landuse_z13 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon_gen1 + ); -- etldoc: osm_landuse_polygon -> landuse_z14 -CREATE OR REPLACE VIEW landuse_z14 AS ( - SELECT osm_id, geometry, landuse, amenity, leisure, tourism, place, waterway - FROM osm_landuse_polygon -); +CREATE OR REPLACE VIEW landuse_z14 AS +( +SELECT osm_id, + geometry, + landuse, + amenity, + leisure, + tourism, + place, + waterway +FROM osm_landuse_polygon + ); -- etldoc: layer_landuse[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_landuse | z4|z5|z6|z7| z8 | z9 | z10 | z11| z12| z13| z14+" ] ; CREATE OR REPLACE FUNCTION layer_landuse(bbox geometry, zoom_level int) -RETURNS TABLE(osm_id bigint, geometry geometry, class text) AS $$ - SELECT osm_id, geometry, - COALESCE( - NULLIF(landuse, ''), - NULLIF(amenity, ''), - NULLIF(leisure, ''), - NULLIF(tourism, ''), - NULLIF(place, ''), - NULLIF(waterway, '') - ) AS class - FROM ( - -- etldoc: landuse_z4 -> layer_landuse:z4 - SELECT * FROM landuse_z4 - WHERE zoom_level = 4 - UNION ALL - -- etldoc: landuse_z5 -> layer_landuse:z5 - SELECT * FROM landuse_z5 - WHERE zoom_level = 5 - UNION ALL - -- etldoc: landuse_z6 -> layer_landuse:z6 - -- etldoc: landuse_z6 -> layer_landuse:z7 - SELECT * FROM landuse_z6 WHERE zoom_level BETWEEN 6 AND 7 - UNION ALL - -- etldoc: landuse_z8 -> layer_landuse:z8 - SELECT * FROM landuse_z8 WHERE zoom_level = 8 - UNION ALL - -- etldoc: landuse_z9 -> layer_landuse:z9 - SELECT * FROM landuse_z9 WHERE zoom_level = 9 - UNION ALL - -- etldoc: landuse_z10 -> layer_landuse:z10 - SELECT * FROM landuse_z10 WHERE zoom_level = 10 - UNION ALL - -- etldoc: landuse_z11 -> layer_landuse:z11 - SELECT * FROM landuse_z11 WHERE zoom_level = 11 - UNION ALL - -- etldoc: landuse_z12 -> layer_landuse:z12 - SELECT * FROM landuse_z12 WHERE zoom_level = 12 - UNION ALL - -- etldoc: landuse_z13 -> layer_landuse:z13 - SELECT * FROM landuse_z13 WHERE zoom_level = 13 - UNION ALL - -- etldoc: landuse_z14 -> layer_landuse:z14 - SELECT * FROM landuse_z14 WHERE zoom_level >= 14 - ) AS zoom_levels - WHERE geometry && bbox; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + class text + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT osm_id, + geometry, + COALESCE( + NULLIF(landuse, ''), + NULLIF(amenity, ''), + NULLIF(leisure, ''), + NULLIF(tourism, ''), + NULLIF(place, ''), + NULLIF(waterway, '') + ) AS class +FROM ( + -- etldoc: landuse_z4 -> layer_landuse:z4 + SELECT * + FROM landuse_z4 + WHERE zoom_level = 4 + UNION ALL + -- etldoc: landuse_z5 -> layer_landuse:z5 + SELECT * + FROM landuse_z5 + WHERE zoom_level = 5 + UNION ALL + -- etldoc: landuse_z6 -> layer_landuse:z6 + -- etldoc: landuse_z6 -> layer_landuse:z7 + SELECT * + FROM landuse_z6 + WHERE zoom_level BETWEEN 6 AND 7 + UNION ALL + -- etldoc: landuse_z8 -> layer_landuse:z8 + SELECT * + FROM landuse_z8 + WHERE zoom_level = 8 + UNION ALL + -- etldoc: landuse_z9 -> layer_landuse:z9 + SELECT * + FROM landuse_z9 + WHERE zoom_level = 9 + UNION ALL + -- etldoc: landuse_z10 -> layer_landuse:z10 + SELECT * + FROM landuse_z10 + WHERE zoom_level = 10 + UNION ALL + -- etldoc: landuse_z11 -> layer_landuse:z11 + SELECT * + FROM landuse_z11 + WHERE zoom_level = 11 + UNION ALL + -- etldoc: landuse_z12 -> layer_landuse:z12 + SELECT * + FROM landuse_z12 + WHERE zoom_level = 12 + UNION ALL + -- etldoc: landuse_z13 -> layer_landuse:z13 + SELECT * + FROM landuse_z13 + WHERE zoom_level = 13 + UNION ALL + -- etldoc: landuse_z14 -> layer_landuse:z14 + SELECT * + FROM landuse_z14 + WHERE zoom_level >= 14 + ) AS zoom_levels +WHERE geometry && bbox; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/mountain_peak/layer.sql b/layers/mountain_peak/layer.sql index 2fb8fa9..9a9385a 100644 --- a/layers/mountain_peak/layer.sql +++ b/layers/mountain_peak/layer.sql @@ -1,57 +1,62 @@ - -- etldoc: layer_mountain_peak[shape=record fillcolor=lightpink, -- etldoc: style="rounded,filled", label="layer_mountain_peak | z7+" ] ; -CREATE OR REPLACE FUNCTION layer_mountain_peak( - bbox geometry, - zoom_level integer, - pixel_width numeric) - RETURNS TABLE( - osm_id bigint, - geometry geometry, - name text, - name_en text, - name_de text, - class text, - tags hstore, - ele int, - ele_ft int, - "rank" int) AS +CREATE OR REPLACE FUNCTION layer_mountain_peak(bbox geometry, + zoom_level integer, + pixel_width numeric) + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + class text, + tags hstore, + ele int, + ele_ft int, + "rank" int + ) +AS $$ - -- etldoc: osm_peak_point -> layer_mountain_peak:z7_ - SELECT +SELECT + -- etldoc: osm_peak_point -> layer_mountain_peak:z7_ osm_id, geometry, name, name_en, name_de, - tags -> 'natural' AS class, + tags->'natural' AS class, tags, ele::int, ele_ft::int, - rank::int FROM ( - SELECT osm_id, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - substring(ele from E'^(-?\\d+)(\\D|$)')::int AS ele, - round(substring(ele from E'^(-?\\d+)(\\D|$)')::int*3.2808399)::int AS ele_ft, - row_number() OVER ( - PARTITION BY LabelGrid(geometry, 100 * pixel_width) - ORDER BY ( - substring(ele from E'^(-?\\d+)(\\D|$)')::int + - (CASE WHEN NULLIF(wikipedia, '') is not null THEN 10000 ELSE 0 END) + - (CASE WHEN NULLIF(name, '') is not null THEN 10000 ELSE 0 END) - ) DESC - )::int AS "rank" - FROM osm_peak_point - WHERE geometry && bbox - AND ele is not null - AND ele ~ E'^-?\\d{1,4}(\\D|$)' - ) AS ranked_peaks - WHERE zoom_level >= 7 AND (rank <= 5 OR zoom_level >= 14) - ORDER BY "rank" ASC; + rank::int +FROM ( + SELECT osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + substring(ele FROM E'^(-?\\d+)(\\D|$)')::int AS ele, + round(substring(ele FROM E'^(-?\\d+)(\\D|$)')::int * 3.2808399)::int AS ele_ft, + row_number() OVER ( + PARTITION BY LabelGrid(geometry, 100 * pixel_width) + ORDER BY ( + substring(ele FROM E'^(-?\\d+)(\\D|$)')::int + + (CASE WHEN NULLIF(wikipedia, '') IS NOT NULL THEN 10000 ELSE 0 END) + + (CASE WHEN NULLIF(name, '') IS NOT NULL THEN 10000 ELSE 0 END) + ) DESC + )::int AS "rank" + FROM osm_peak_point + WHERE geometry && bbox + AND ele IS NOT NULL + AND ele ~ E'^-?\\d{1,4}(\\D|$)' + ) AS ranked_peaks +WHERE zoom_level >= 7 + AND (rank <= 5 OR zoom_level >= 14) +ORDER BY "rank" ASC; -$$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +$$ LANGUAGE SQL STABLE + PARALLEL SAFE; +-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL diff --git a/layers/mountain_peak/update_peak_point.sql b/layers/mountain_peak/update_peak_point.sql index 666bf97..db0b3ae 100644 --- a/layers/mountain_peak/update_peak_point.sql +++ b/layers/mountain_peak/update_peak_point.sql @@ -1,48 +1,33 @@ -DROP TRIGGER IF EXISTS trigger_flag ON osm_peak_point; -DROP TRIGGER IF EXISTS trigger_refresh ON mountain_peak_point.updates; +DROP TRIGGER IF EXISTS trigger_update_point ON osm_peak_point; -- etldoc: osm_peak_point -> osm_peak_point -CREATE OR REPLACE FUNCTION update_osm_peak_point() RETURNS VOID AS $$ -BEGIN - UPDATE osm_peak_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; +-- etldoc: osm_peak_point -> osm_peak_point +CREATE OR REPLACE FUNCTION update_osm_peak_point(new_osm_id bigint) RETURNS void AS +$$ +UPDATE osm_peak_point +SET tags = update_tags(tags, geometry) +WHERE (new_osm_id IS NULL OR osm_id = new_osm_id) + AND COALESCE(tags -> 'name:latin', tags -> 'name:nonlatin', tags -> 'name_int') IS NULL + AND tags != update_tags(tags, geometry) +$$ LANGUAGE SQL; -END; -$$ LANGUAGE plpgsql; - -SELECT update_osm_peak_point(); +SELECT update_osm_peak_point(NULL); -- Handle updates CREATE SCHEMA IF NOT EXISTS mountain_peak_point; -CREATE TABLE IF NOT EXISTS mountain_peak_point.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION mountain_peak_point.flag() RETURNS trigger AS $$ +CREATE OR REPLACE FUNCTION mountain_peak_point.update() RETURNS trigger AS +$$ BEGIN - INSERT INTO mountain_peak_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + PERFORM update_osm_peak_point(new.osm_id); + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION mountain_peak_point.refresh() RETURNS trigger AS - $BODY$ - BEGIN - RAISE LOG 'Refresh mountain_peak_point'; - PERFORM update_osm_peak_point(); - DELETE FROM mountain_peak_point.updates; - RETURN null; - END; - $BODY$ -language plpgsql; - -CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_peak_point - FOR EACH STATEMENT - EXECUTE PROCEDURE mountain_peak_point.flag(); - -CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON mountain_peak_point.updates +CREATE CONSTRAINT TRIGGER trigger_update_point + AFTER INSERT OR UPDATE + ON osm_peak_point INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE mountain_peak_point.refresh(); +EXECUTE PROCEDURE mountain_peak_point.update(); diff --git a/layers/park/layer.sql b/layers/park/layer.sql index bb8162a..e6547c8 100644 --- a/layers/park/layer.sql +++ b/layers/park/layer.sql @@ -2,134 +2,340 @@ -- etldoc: label="layer_park | z6 | z7 | z8 | z9 | z10 | z11 | z12| z13| z14+" ] ; CREATE OR REPLACE FUNCTION layer_park(bbox geometry, zoom_level int, pixel_width numeric) -RETURNS TABLE(osm_id bigint, geometry geometry, class text, name text, name_en text, name_de text, tags hstore, rank int) AS $$ - SELECT osm_id, geometry, class, name, name_en, name_de, tags, rank - FROM ( - SELECT osm_id, geometry, - COALESCE( - LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')), - NULLIF(boundary, ''), - NULLIF(leisure, '') - ) AS class, - name, name_en, name_de, tags, - NULL::int as rank - FROM ( - -- etldoc: osm_park_polygon_gen8 -> layer_park:z6 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen8 - WHERE zoom_level = 6 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen7 -> layer_park:z7 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen7 - WHERE zoom_level = 7 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen6 -> layer_park:z8 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen6 - WHERE zoom_level = 8 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen5 -> layer_park:z9 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen5 - WHERE zoom_level = 9 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen4 -> layer_park:z10 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen4 - WHERE zoom_level = 10 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen3 -> layer_park:z11 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen3 - WHERE zoom_level = 11 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen2 -> layer_park:z12 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen2 - WHERE zoom_level = 12 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon_gen1 -> layer_park:z13 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon_gen1 - WHERE zoom_level = 13 AND geometry && bbox - UNION ALL - -- etldoc: osm_park_polygon -> layer_park:z14 - SELECT osm_id, geometry, name, name_en, name_de, tags, leisure, boundary, protection_title - FROM osm_park_polygon - WHERE zoom_level >= 14 AND geometry && bbox - ) AS park_polygon - - UNION ALL - SELECT osm_id, geometry_point AS geometry, - COALESCE( - LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')), - NULLIF(boundary, ''), - NULLIF(leisure, '') - ) AS class, - name, name_en, name_de, tags, - row_number() OVER ( - PARTITION BY LabelGrid(geometry_point, 100 * pixel_width) - ORDER BY - (CASE WHEN boundary = 'national_park' THEN true ELSE false END) DESC, - (COALESCE(NULLIF(tags->'wikipedia', ''), NULLIF(tags->'wikidata', '')) IS NOT NULL) DESC, - area DESC - )::int AS "rank" - FROM ( - -- etldoc: osm_park_polygon_gen8 -> layer_park:z6 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen8 - WHERE zoom_level = 6 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen7 -> layer_park:z7 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen7 - WHERE zoom_level = 7 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen6 -> layer_park:z8 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen6 - WHERE zoom_level = 8 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen5 -> layer_park:z9 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen5 - WHERE zoom_level = 9 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen4 -> layer_park:z10 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen4 - WHERE zoom_level = 10 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen3 -> layer_park:z11 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen3 - WHERE zoom_level = 11 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen2 -> layer_park:z12 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen2 - WHERE zoom_level = 12 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon_gen1 -> layer_park:z13 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon_gen1 - WHERE zoom_level = 13 AND geometry_point && bbox - UNION ALL - - -- etldoc: osm_park_polygon -> layer_park:z14 - SELECT osm_id, geometry_point, name, name_en, name_de, tags, leisure, boundary, protection_title, area - FROM osm_park_polygon - WHERE zoom_level >= 14 AND geometry_point && bbox - ) AS park_point - ) AS park_all; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + class text, + name text, + name_en text, + name_de text, + tags hstore, + rank int + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT osm_id, + geometry, + class, + name, + name_en, + name_de, + tags, + rank +FROM ( + SELECT osm_id, + geometry, + COALESCE( + LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')), + NULLIF(boundary, ''), + NULLIF(leisure, '') + ) AS class, + name, + name_en, + name_de, + tags, + NULL::int AS rank + FROM ( + -- etldoc: osm_park_polygon_gen8 -> layer_park:z6 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen8 + WHERE zoom_level = 6 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen7 -> layer_park:z7 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen7 + WHERE zoom_level = 7 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen6 -> layer_park:z8 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen6 + WHERE zoom_level = 8 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen5 -> layer_park:z9 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen5 + WHERE zoom_level = 9 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen4 -> layer_park:z10 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen4 + WHERE zoom_level = 10 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen3 -> layer_park:z11 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen3 + WHERE zoom_level = 11 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen2 -> layer_park:z12 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen2 + WHERE zoom_level = 12 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon_gen1 -> layer_park:z13 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon_gen1 + WHERE zoom_level = 13 + AND geometry && bbox + UNION ALL + -- etldoc: osm_park_polygon -> layer_park:z14 + SELECT osm_id, + geometry, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title + FROM osm_park_polygon + WHERE zoom_level >= 14 + AND geometry && bbox + ) AS park_polygon + + UNION ALL + SELECT osm_id, + geometry_point AS geometry, + COALESCE( + LOWER(REPLACE(NULLIF(protection_title, ''), ' ', '_')), + NULLIF(boundary, ''), + NULLIF(leisure, '') + ) AS class, + name, + name_en, + name_de, + tags, + row_number() OVER ( + PARTITION BY LabelGrid(geometry_point, 100 * pixel_width) + ORDER BY + (CASE WHEN boundary = 'national_park' THEN TRUE ELSE FALSE END) DESC, + (COALESCE(NULLIF(tags->'wikipedia', ''), NULLIF(tags->'wikidata', '')) IS NOT NULL) DESC, + area DESC + )::int AS "rank" + FROM ( + -- etldoc: osm_park_polygon_gen8 -> layer_park:z6 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen8 + WHERE zoom_level = 6 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen7 -> layer_park:z7 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen7 + WHERE zoom_level = 7 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen6 -> layer_park:z8 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen6 + WHERE zoom_level = 8 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen5 -> layer_park:z9 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen5 + WHERE zoom_level = 9 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen4 -> layer_park:z10 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen4 + WHERE zoom_level = 10 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen3 -> layer_park:z11 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen3 + WHERE zoom_level = 11 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen2 -> layer_park:z12 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen2 + WHERE zoom_level = 12 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon_gen1 -> layer_park:z13 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon_gen1 + WHERE zoom_level = 13 + AND geometry_point && bbox + AND area > 70000*2^(20-zoom_level) + UNION ALL + + -- etldoc: osm_park_polygon -> layer_park:z14 + SELECT osm_id, + geometry_point, + name, + name_en, + name_de, + tags, + leisure, + boundary, + protection_title, + area + FROM osm_park_polygon + WHERE zoom_level >= 14 + AND geometry_point && bbox + ) AS park_point + ) AS park_all; +$$ LANGUAGE SQL STABLE + PARALLEL SAFE; +-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL diff --git a/layers/park/update_park_polygon.sql b/layers/park/update_park_polygon.sql index 1dabc00..23fe2f6 100644 --- a/layers/park/update_park_polygon.sql +++ b/layers/park/update_park_polygon.sql @@ -1,12 +1,22 @@ -ALTER TABLE osm_park_polygon ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen1 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen2 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen3 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen4 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen5 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen6 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen7 ADD COLUMN IF NOT EXISTS geometry_point geometry; -ALTER TABLE osm_park_polygon_gen8 ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen1 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen2 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen3 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen4 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen5 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen6 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen7 + ADD COLUMN IF NOT EXISTS geometry_point geometry; +ALTER TABLE osm_park_polygon_gen8 + ADD COLUMN IF NOT EXISTS geometry_point geometry; + DROP TRIGGER IF EXISTS update_row ON osm_park_polygon; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen1; DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen2; @@ -26,115 +36,121 @@ DROP TRIGGER IF EXISTS update_row ON osm_park_polygon_gen8; -- etldoc: osm_park_polygon_gen6 -> osm_park_polygon_gen6 -- etldoc: osm_park_polygon_gen7 -> osm_park_polygon_gen7 -- etldoc: osm_park_polygon_gen8 -> osm_park_polygon_gen8 -CREATE OR REPLACE FUNCTION update_osm_park_polygon() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_park_polygon() RETURNS void AS +$$ BEGIN - UPDATE osm_park_polygon - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen1 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen1 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen2 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen2 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen3 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen3 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen4 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen4 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen5 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen5 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen6 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen6 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen7 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen7 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); - UPDATE osm_park_polygon_gen8 - SET tags = update_tags(tags, geometry), - geometry_point = st_centroid(geometry); + UPDATE osm_park_polygon_gen8 + SET tags = update_tags(tags, geometry), + geometry_point = st_centroid(geometry); END; $$ LANGUAGE plpgsql; SELECT update_osm_park_polygon(); -CREATE INDEX IF NOT EXISTS osm_park_polygon_point_geom_idx ON osm_park_polygon USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen1_point_geom_idx ON osm_park_polygon_gen1 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen2_point_geom_idx ON osm_park_polygon_gen2 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen3_point_geom_idx ON osm_park_polygon_gen3 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen4_point_geom_idx ON osm_park_polygon_gen4 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen5_point_geom_idx ON osm_park_polygon_gen5 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen6_point_geom_idx ON osm_park_polygon_gen6 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen7_point_geom_idx ON osm_park_polygon_gen7 USING gist(geometry_point); -CREATE INDEX IF NOT EXISTS osm_park_polygon_gen8_point_geom_idx ON osm_park_polygon_gen8 USING gist(geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_point_geom_idx ON osm_park_polygon USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen1_point_geom_idx ON osm_park_polygon_gen1 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen2_point_geom_idx ON osm_park_polygon_gen2 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen3_point_geom_idx ON osm_park_polygon_gen3 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen4_point_geom_idx ON osm_park_polygon_gen4 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen5_point_geom_idx ON osm_park_polygon_gen5 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen6_point_geom_idx ON osm_park_polygon_gen6 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen7_point_geom_idx ON osm_park_polygon_gen7 USING gist (geometry_point); +CREATE INDEX IF NOT EXISTS osm_park_polygon_gen8_point_geom_idx ON osm_park_polygon_gen8 USING gist (geometry_point); CREATE OR REPLACE FUNCTION update_osm_park_polygon_row() - RETURNS TRIGGER + RETURNS trigger AS -$BODY$ +$$ BEGIN - NEW.tags = update_tags(NEW.tags, NEW.geometry); - NEW.geometry_point = st_centroid(NEW.geometry); - RETURN NEW; + NEW.tags = update_tags(NEW.tags, NEW.geometry); + NEW.geometry_point = st_centroid(NEW.geometry); + RETURN NEW; END; -$BODY$ -LANGUAGE plpgsql; +$$ LANGUAGE plpgsql; CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen1 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen1 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen2 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen2 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen3 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen3 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen4 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen4 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen5 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen5 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen6 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen6 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen7 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen7 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); CREATE TRIGGER update_row -BEFORE INSERT OR UPDATE ON osm_park_polygon_gen8 -FOR EACH ROW + BEFORE INSERT OR UPDATE + ON osm_park_polygon_gen8 + FOR EACH ROW EXECUTE PROCEDURE update_osm_park_polygon_row(); - - - diff --git a/layers/place/capital.sql b/layers/place/capital.sql index 434d3fb..3375647 100644 --- a/layers/place/capital.sql +++ b/layers/place/capital.sql @@ -1,9 +1,10 @@ -CREATE OR REPLACE FUNCTION normalize_capital_level(capital TEXT) -RETURNS INT AS $$ - SELECT CASE - WHEN capital IN ('yes', '2') THEN 2 - WHEN capital = '4' THEN 4 - END; +CREATE OR REPLACE FUNCTION normalize_capital_level(capital text) + RETURNS int AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN capital IN ('yes', '2') THEN 2 + WHEN capital = '4' THEN 4 + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; diff --git a/layers/place/city.sql b/layers/place/city.sql index e3ef2d6..9c44e4f 100644 --- a/layers/place/city.sql +++ b/layers/place/city.sql @@ -1,57 +1,79 @@ - -- etldoc: layer_city[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_city | z2-z14+" ] ; -- etldoc: osm_city_point -> layer_city:z2_14 CREATE OR REPLACE FUNCTION layer_city(bbox geometry, zoom_level int, pixel_width numeric) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, name_de text, tags hstore, place city_place, "rank" int, capital int) AS $$ - SELECT * FROM ( - SELECT osm_id, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - place, "rank", normalize_capital_level(capital) AS capital - FROM osm_city_point - WHERE geometry && bbox - AND ((zoom_level = 2 AND "rank" = 1) - OR (zoom_level BETWEEN 3 AND 7 AND "rank" <= zoom_level + 1) - ) - UNION ALL - SELECT osm_id, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - place, - COALESCE("rank", gridrank + 10), - normalize_capital_level(capital) AS capital - FROM ( - SELECT osm_id, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - place, "rank", capital, - row_number() OVER ( - PARTITION BY LabelGrid(geometry, 128 * pixel_width) - ORDER BY "rank" ASC NULLS LAST, - place ASC NULLS LAST, - population DESC NULLS LAST, - length(name) ASC - )::int AS gridrank - FROM osm_city_point - WHERE geometry && bbox - AND ((zoom_level = 7 AND place <= 'town'::city_place - OR (zoom_level BETWEEN 8 AND 10 AND place <= 'village'::city_place) - - OR (zoom_level BETWEEN 11 AND 13 AND place <= 'suburb'::city_place) - OR (zoom_level >= 14) - )) - ) AS ranked_places - WHERE (zoom_level BETWEEN 7 AND 8 AND (gridrank <= 4 OR "rank" IS NOT NULL)) - OR (zoom_level = 9 AND (gridrank <= 8 OR "rank" IS NOT NULL)) - OR (zoom_level = 10 AND (gridrank <= 12 OR "rank" IS NOT NULL)) - OR (zoom_level BETWEEN 11 AND 12 AND (gridrank <= 14 OR "rank" IS NOT NULL)) - OR (zoom_level >= 13) - ) as city_all; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + tags hstore, + place city_place, + "rank" int, + capital int + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT * +FROM ( + SELECT osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + place, + "rank", + normalize_capital_level(capital) AS capital + FROM osm_city_point + WHERE geometry && bbox + AND ((zoom_level = 2 AND "rank" = 1) + OR (zoom_level BETWEEN 3 AND 7 AND "rank" <= zoom_level + 1) + ) + UNION ALL + SELECT osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + place, + COALESCE("rank", gridrank + 10), + normalize_capital_level(capital) AS capital + FROM ( + SELECT osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + place, + "rank", + capital, + row_number() OVER ( + PARTITION BY LabelGrid(geometry, 128 * pixel_width) + ORDER BY "rank" ASC NULLS LAST, + place ASC NULLS LAST, + population DESC NULLS LAST, + length(name) ASC + )::int AS gridrank + FROM osm_city_point + WHERE geometry && bbox + AND ((zoom_level = 7 AND place <= 'town'::city_place + OR (zoom_level BETWEEN 8 AND 10 AND place <= 'village'::city_place) + OR (zoom_level BETWEEN 11 AND 13 AND place <= 'suburb'::city_place) + OR (zoom_level >= 14) + )) + ) AS ranked_places + WHERE (zoom_level BETWEEN 7 AND 8 AND (gridrank <= 4 OR "rank" IS NOT NULL)) + OR (zoom_level = 9 AND (gridrank <= 8 OR "rank" IS NOT NULL)) + OR (zoom_level = 10 AND (gridrank <= 12 OR "rank" IS NOT NULL)) + OR (zoom_level BETWEEN 11 AND 12 AND (gridrank <= 14 OR "rank" IS NOT NULL)) + OR (zoom_level >= 13) + ) AS city_all; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/place/island_rank.sql b/layers/place/island_rank.sql index 15b8d5a..f7ef3ef 100644 --- a/layers/place/island_rank.sql +++ b/layers/place/island_rank.sql @@ -1,11 +1,12 @@ -CREATE OR REPLACE FUNCTION island_rank(area REAL) RETURNS INT AS $$ - SELECT CASE - WHEN area < 10000000 THEN 6 - WHEN area BETWEEN 1000000 AND 15000000 THEN 5 - WHEN area BETWEEN 15000000 AND 40000000 THEN 4 - WHEN area > 40000000 THEN 3 - ELSE 7 - END; +CREATE OR REPLACE FUNCTION island_rank(area real) RETURNS int AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN area < 10000000 THEN 6 + WHEN area BETWEEN 1000000 AND 15000000 THEN 5 + WHEN area BETWEEN 15000000 AND 40000000 THEN 4 + WHEN area > 40000000 THEN 3 + ELSE 7 + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; diff --git a/layers/place/layer.sql b/layers/place/layer.sql index f4d3d40..f4eae73 100644 --- a/layers/place/layer.sql +++ b/layers/place/layer.sql @@ -1,101 +1,147 @@ - -- etldoc: layer_place[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_place | z0-3| z4-7| z8-11| z12-z14+" ] ; CREATE OR REPLACE FUNCTION layer_place(bbox geometry, zoom_level int, pixel_width numeric) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, - name_de text, tags hstore, class text, "rank" int, capital INT, iso_a2 - TEXT) AS $$ - SELECT * FROM ( - - -- etldoc: osm_continent_point -> layer_place:z0_3 - SELECT - osm_id*10, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - 'continent' AS class, 1 AS "rank", NULL::int AS capital, - NULL::text AS iso_a2 - FROM osm_continent_point - WHERE geometry && bbox AND zoom_level < 4 - UNION ALL - - -- etldoc: osm_country_point -> layer_place:z0_3 - -- etldoc: osm_country_point -> layer_place:z4_7 - -- etldoc: osm_country_point -> layer_place:z8_11 - -- etldoc: osm_country_point -> layer_place:z12_14 - SELECT - osm_id*10, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - 'country' AS class, "rank", NULL::int AS capital, - iso3166_1_alpha_2 AS iso_a2 - FROM osm_country_point - WHERE geometry && bbox AND "rank" <= zoom_level + 1 AND name <> '' - UNION ALL - - -- etldoc: osm_state_point -> layer_place:z0_3 - -- etldoc: osm_state_point -> layer_place:z4_7 - -- etldoc: osm_state_point -> layer_place:z8_11 - -- etldoc: osm_state_point -> layer_place:z12_14 - SELECT - osm_id*10, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - 'state' AS class, "rank", NULL::int AS capital, - NULL::text AS iso_a2 - FROM osm_state_point - WHERE geometry && bbox AND - name <> '' AND - ("rank" + 2 <= zoom_level) AND ( - zoom_level >= 5 OR - is_in_country IN ('United Kingdom', 'USA', 'Россия', 'Brasil', 'China', 'India') OR - is_in_country_code IN ('AU', 'CN', 'IN', 'BR', 'US')) - UNION ALL - - -- etldoc: osm_island_point -> layer_place:z12_14 - SELECT - osm_id*10, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - 'island' AS class, 7 AS "rank", NULL::int AS capital, - NULL::text AS iso_a2 - FROM osm_island_point - WHERE zoom_level >= 12 - AND geometry && bbox - UNION ALL - - -- etldoc: osm_island_polygon -> layer_place:z8_11 - -- etldoc: osm_island_polygon -> layer_place:z12_14 - SELECT - osm_id*10, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - 'island' AS class, island_rank(area) AS "rank", NULL::int AS capital, - NULL::text AS iso_a2 - FROM osm_island_polygon - WHERE geometry && bbox AND - ((zoom_level = 8 AND island_rank(area) <= 3) - OR (zoom_level = 9 AND island_rank(area) <= 4) - OR (zoom_level >= 10)) - UNION ALL - - -- etldoc: layer_city -> layer_place:z0_3 - -- etldoc: layer_city -> layer_place:z4_7 - -- etldoc: layer_city -> layer_place:z8_11 - -- etldoc: layer_city -> layer_place:z12_14 - SELECT - osm_id*10, geometry, name, name_en, name_de, - tags, - place::text AS class, "rank", capital, - NULL::text AS iso_a2 - FROM layer_city(bbox, zoom_level, pixel_width) - ORDER BY "rank" ASC - ) AS place_all + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + tags hstore, + class text, + "rank" int, + capital int, + iso_a2 text + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT * +FROM ( + SELECT + -- etldoc: osm_continent_point -> layer_place:z0_3 + osm_id * 10 AS osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + 'continent' AS class, + 1 AS "rank", + NULL::int AS capital, + NULL::text AS iso_a2 + FROM osm_continent_point + WHERE geometry && bbox + AND zoom_level < 4 + + UNION ALL + + SELECT + -- etldoc: osm_country_point -> layer_place:z0_3 + -- etldoc: osm_country_point -> layer_place:z4_7 + -- etldoc: osm_country_point -> layer_place:z8_11 + -- etldoc: osm_country_point -> layer_place:z12_14 + osm_id * 10 AS osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + 'country' AS class, + "rank", + NULL::int AS capital, + iso3166_1_alpha_2 AS iso_a2 + FROM osm_country_point + WHERE geometry && bbox + AND "rank" <= zoom_level + 1 + AND name <> '' + + UNION ALL + + SELECT + -- etldoc: osm_state_point -> layer_place:z0_3 + -- etldoc: osm_state_point -> layer_place:z4_7 + -- etldoc: osm_state_point -> layer_place:z8_11 + -- etldoc: osm_state_point -> layer_place:z12_14 + osm_id * 10 AS osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + 'state' AS class, + "rank", + NULL::int AS capital, + NULL::text AS iso_a2 + FROM osm_state_point + WHERE geometry && bbox + AND name <> '' + AND ("rank" + 2 <= zoom_level) + AND ( + zoom_level >= 5 OR + is_in_country IN ('United Kingdom', 'USA', 'Россия', 'Brasil', 'China', 'India') OR + is_in_country_code IN ('AU', 'CN', 'IN', 'BR', 'US')) + + UNION ALL + + SELECT + -- etldoc: osm_island_point -> layer_place:z12_14 + osm_id * 10 AS osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + 'island' AS class, + 7 AS "rank", + NULL::int AS capital, + NULL::text AS iso_a2 + FROM osm_island_point + WHERE zoom_level >= 12 + AND geometry && bbox + + UNION ALL + + SELECT + -- etldoc: osm_island_polygon -> layer_place:z8_11 + -- etldoc: osm_island_polygon -> layer_place:z12_14 + osm_id * 10 AS osm_id, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + 'island' AS class, + island_rank(area) AS "rank", + NULL::int AS capital, + NULL::text AS iso_a2 + FROM osm_island_polygon + WHERE geometry && bbox + AND ((zoom_level = 8 AND island_rank(area) <= 3) + OR (zoom_level = 9 AND island_rank(area) <= 4) + OR (zoom_level >= 10)) + + UNION ALL + + SELECT + -- etldoc: layer_city -> layer_place:z0_3 + -- etldoc: layer_city -> layer_place:z4_7 + -- etldoc: layer_city -> layer_place:z8_11 + -- etldoc: layer_city -> layer_place:z12_14 + osm_id * 10 AS osm_id, + geometry, + name, + name_en, + name_de, + tags, + place::text AS class, + "rank", + capital, + NULL::text AS iso_a2 + FROM layer_city(bbox, zoom_level, pixel_width) + ORDER BY "rank" ASC + ) AS place_all +$$ LANGUAGE SQL STABLE + PARALLEL SAFE; +-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL diff --git a/layers/place/types.sql b/layers/place/types.sql index f7fdedf..1ecdd3b 100644 --- a/layers/place/types.sql +++ b/layers/place/types.sql @@ -1,9 +1,11 @@ -DO $$ -BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'city_place') THEN - CREATE TYPE city_place AS ENUM ('city', 'town', 'village', 'hamlet', 'suburb', 'neighbourhood', 'isolated_dwelling'); - END IF; -END +DO +$$ + BEGIN + IF NOT EXISTS(SELECT 1 FROM pg_type WHERE typname = 'city_place') THEN + CREATE TYPE city_place AS enum ('city', 'town', 'village', 'hamlet', 'suburb', 'neighbourhood', 'isolated_dwelling'); + END IF; + END $$; -ALTER TABLE osm_city_point ALTER COLUMN place TYPE city_place USING place::city_place; +ALTER TABLE osm_city_point + ALTER COLUMN place TYPE city_place USING place::city_place; diff --git a/layers/place/update_city_point.sql b/layers/place/update_city_point.sql index 1dae791..7766491 100644 --- a/layers/place/update_city_point.sql +++ b/layers/place/update_city_point.sql @@ -3,85 +3,94 @@ DROP TRIGGER IF EXISTS trigger_refresh ON place_city.updates; CREATE EXTENSION IF NOT EXISTS unaccent; -CREATE OR REPLACE FUNCTION update_osm_city_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_city_point() RETURNS void AS +$$ BEGIN - -- Clear OSM key:rank ( https://github.com/openmaptiles/openmaptiles/issues/108 ) - -- etldoc: osm_city_point -> osm_city_point - UPDATE osm_city_point AS osm SET "rank" = NULL WHERE "rank" IS NOT NULL; + -- Clear OSM key:rank ( https://github.com/openmaptiles/openmaptiles/issues/108 ) + -- etldoc: osm_city_point -> osm_city_point + UPDATE osm_city_point AS osm SET "rank" = NULL WHERE "rank" IS NOT NULL; - -- etldoc: ne_10m_populated_places -> osm_city_point - -- etldoc: osm_city_point -> osm_city_point + -- etldoc: ne_10m_populated_places -> osm_city_point + -- etldoc: osm_city_point -> osm_city_point - WITH important_city_point AS ( - SELECT osm.geometry, osm.osm_id, osm.name, osm.name_en, ne.scalerank, ne.labelrank - FROM ne_10m_populated_places AS ne, osm_city_point AS osm - WHERE - ( - (osm.tags ? 'wikidata' AND osm.tags->'wikidata' = ne.wikidataid) OR - ne.name ILIKE osm.name OR - ne.name ILIKE osm.name_en OR - ne.namealt ILIKE osm.name OR - ne.namealt ILIKE osm.name_en OR - ne.meganame ILIKE osm.name OR - ne.meganame ILIKE osm.name_en OR - ne.gn_ascii ILIKE osm.name OR - ne.gn_ascii ILIKE osm.name_en OR - ne.nameascii ILIKE osm.name OR - ne.nameascii ILIKE osm.name_en OR - ne.name = unaccent(osm.name) - ) - AND osm.place IN ('city', 'town', 'village') - AND ST_DWithin(ne.geometry, osm.geometry, 50000) - ) - UPDATE osm_city_point AS osm - -- Move scalerank to range 1 to 10 and merge scalerank 5 with 6 since not enough cities - -- are in the scalerank 5 bucket - SET "rank" = CASE WHEN scalerank <= 5 THEN scalerank + 1 ELSE scalerank END - FROM important_city_point AS ne - WHERE osm.osm_id = ne.osm_id; + WITH important_city_point AS ( + SELECT osm.geometry, osm.osm_id, osm.name, osm.name_en, ne.scalerank, ne.labelrank + FROM ne_10m_populated_places AS ne, + osm_city_point AS osm + WHERE ( + (osm.tags ? 'wikidata' AND osm.tags->'wikidata' = ne.wikidataid) OR + ne.name ILIKE osm.name OR + ne.name ILIKE osm.name_en OR + ne.namealt ILIKE osm.name OR + ne.namealt ILIKE osm.name_en OR + ne.meganame ILIKE osm.name OR + ne.meganame ILIKE osm.name_en OR + ne.gn_ascii ILIKE osm.name OR + ne.gn_ascii ILIKE osm.name_en OR + ne.nameascii ILIKE osm.name OR + ne.nameascii ILIKE osm.name_en OR + ne.name = unaccent(osm.name) + ) + AND osm.place IN ('city', 'town', 'village') + AND ST_DWithin(ne.geometry, osm.geometry, 50000) + ) + UPDATE osm_city_point AS osm + -- Move scalerank to range 1 to 10 and merge scalerank 5 with 6 since not enough cities + -- are in the scalerank 5 bucket + SET "rank" = CASE WHEN scalerank <= 5 THEN scalerank + 1 ELSE scalerank END + FROM important_city_point AS ne + WHERE osm.osm_id = ne.osm_id; - UPDATE osm_city_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_city_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; SELECT update_osm_city_point(); -CREATE INDEX IF NOT EXISTS osm_city_point_rank_idx ON osm_city_point("rank"); +CREATE INDEX IF NOT EXISTS osm_city_point_rank_idx ON osm_city_point ("rank"); -- Handle updates CREATE SCHEMA IF NOT EXISTS place_city; -CREATE TABLE IF NOT EXISTS place_city.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION place_city.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS place_city.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION place_city.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO place_city.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO place_city.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION place_city.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh place_city rank'; PERFORM update_osm_city_point(); + -- noinspection SqlWithoutWhere DELETE FROM place_city.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_city_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_city_point FOR EACH STATEMENT - EXECUTE PROCEDURE place_city.flag(); +EXECUTE PROCEDURE place_city.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON place_city.updates + AFTER INSERT + ON place_city.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE place_city.refresh(); \ No newline at end of file +EXECUTE PROCEDURE place_city.refresh(); diff --git a/layers/place/update_continent_point.sql b/layers/place/update_continent_point.sql index 9e48c54..6502299 100644 --- a/layers/place/update_continent_point.sql +++ b/layers/place/update_continent_point.sql @@ -2,11 +2,12 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_continent_point; DROP TRIGGER IF EXISTS trigger_refresh ON place_continent_point.updates; -- etldoc: osm_continent_point -> osm_continent_point -CREATE OR REPLACE FUNCTION update_osm_continent_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_continent_point() RETURNS void AS +$$ BEGIN - UPDATE osm_continent_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_continent_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; @@ -17,32 +18,40 @@ SELECT update_osm_continent_point(); CREATE SCHEMA IF NOT EXISTS place_continent_point; -CREATE TABLE IF NOT EXISTS place_continent_point.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION place_continent_point.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS place_continent_point.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION place_continent_point.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO place_continent_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO place_continent_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION place_continent_point.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh place_continent_point'; PERFORM update_osm_continent_point(); + -- noinspection SqlWithoutWhere DELETE FROM place_continent_point.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_continent_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_continent_point FOR EACH STATEMENT - EXECUTE PROCEDURE place_continent_point.flag(); +EXECUTE PROCEDURE place_continent_point.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON place_continent_point.updates + AFTER INSERT + ON place_continent_point.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE place_continent_point.refresh(); +EXECUTE PROCEDURE place_continent_point.refresh(); diff --git a/layers/place/update_country_point.sql b/layers/place/update_country_point.sql index 175a722..a49e3b6 100644 --- a/layers/place/update_country_point.sql +++ b/layers/place/update_country_point.sql @@ -1,80 +1,85 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_country_point; DROP TRIGGER IF EXISTS trigger_refresh ON place_country.updates; -ALTER TABLE osm_country_point DROP CONSTRAINT IF EXISTS osm_country_point_rank_constraint; +ALTER TABLE osm_country_point + DROP CONSTRAINT IF EXISTS osm_country_point_rank_constraint; -- etldoc: ne_10m_admin_0_countries -> osm_country_point -- etldoc: osm_country_point -> osm_country_point -CREATE OR REPLACE FUNCTION update_osm_country_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_country_point() RETURNS void AS +$$ BEGIN - UPDATE osm_country_point AS osm - SET - "rank" = 7, - iso3166_1_alpha_2 = COALESCE( - NULLIF(osm.country_code_iso3166_1_alpha_2, ''), - NULLIF(osm.iso3166_1_alpha_2, ''), - NULLIF(osm.iso3166_1, '') + UPDATE osm_country_point AS osm + SET "rank" = 7, + iso3166_1_alpha_2 = COALESCE( + NULLIF(osm.country_code_iso3166_1_alpha_2, ''), + NULLIF(osm.iso3166_1_alpha_2, ''), + NULLIF(osm.iso3166_1, '') + ); + + WITH important_country_point AS ( + SELECT osm.geometry, + osm.osm_id, + osm.name, + COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en, + ne.scalerank, + ne.labelrank + FROM ne_10m_admin_0_countries AS ne, + osm_country_point AS osm + WHERE + -- We match only countries with ISO codes to eliminate disputed countries + iso3166_1_alpha_2 IS NOT NULL + -- that lies inside polygon of sovereign country + AND ST_Within(osm.geometry, ne.geometry) ) - ; + UPDATE osm_country_point AS osm + -- Normalize both scalerank and labelrank into a ranking system from 1 to 6 + -- where the ranks are still distributed uniform enough across all countries + SET "rank" = LEAST(6, CEILING((scalerank + labelrank) / 2.0)) + FROM important_country_point AS ne + WHERE osm.osm_id = ne.osm_id; - WITH important_country_point AS ( - SELECT osm.geometry, osm.osm_id, osm.name, COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en, ne.scalerank, ne.labelrank - FROM ne_10m_admin_0_countries AS ne, osm_country_point AS osm - WHERE - -- We match only countries with ISO codes to eliminate disputed countries - iso3166_1_alpha_2 IS NOT NULL - -- that lies inside polygon of sovereign country - AND ST_Within(osm.geometry, ne.geometry) - ) - UPDATE osm_country_point AS osm - -- Normalize both scalerank and labelrank into a ranking system from 1 to 6 - -- where the ranks are still distributed uniform enough across all countries - SET "rank" = LEAST(6, CEILING((scalerank + labelrank)/2.0)) - FROM important_country_point AS ne - WHERE osm.osm_id = ne.osm_id; - - -- Repeat the step for archipelago countries like Philippines or Indonesia - -- whose label point is not within country's polygon - WITH important_country_point AS ( - SELECT - osm.osm_id, + -- Repeat the step for archipelago countries like Philippines or Indonesia + -- whose label point is not within country's polygon + WITH important_country_point AS ( + SELECT osm.osm_id, -- osm.name, - ne.scalerank, - ne.labelrank, + ne.scalerank, + ne.labelrank, -- ST_Distance(osm.geometry, ne.geometry) AS distance, - ROW_NUMBER() - OVER ( - PARTITION BY osm.osm_id - ORDER BY - ST_Distance(osm.geometry, ne.geometry) - ) AS rk - FROM osm_country_point osm, - ne_10m_admin_0_countries AS ne - WHERE - iso3166_1_alpha_2 IS NOT NULL - AND NOT (osm."rank" BETWEEN 1 AND 6) - ) - UPDATE osm_country_point AS osm - -- Normalize both scalerank and labelrank into a ranking system from 1 to 6 - -- where the ranks are still distributed uniform enough across all countries - SET "rank" = LEAST(6, CEILING((ne.scalerank + ne.labelrank)/2.0)) - FROM important_country_point AS ne - WHERE osm.osm_id = ne.osm_id AND ne.rk = 1; + ROW_NUMBER() + OVER ( + PARTITION BY osm.osm_id + ORDER BY + ST_Distance(osm.geometry, ne.geometry) + ) AS rk + FROM osm_country_point osm, + ne_10m_admin_0_countries AS ne + WHERE iso3166_1_alpha_2 IS NOT NULL + AND NOT (osm."rank" BETWEEN 1 AND 6) + ) + UPDATE osm_country_point AS osm + -- Normalize both scalerank and labelrank into a ranking system from 1 to 6 + -- where the ranks are still distributed uniform enough across all countries + SET "rank" = LEAST(6, CEILING((ne.scalerank + ne.labelrank) / 2.0)) + FROM important_country_point AS ne + WHERE osm.osm_id = ne.osm_id + AND ne.rk = 1; - UPDATE osm_country_point AS osm - SET "rank" = 6 - WHERE "rank" = 7; + UPDATE osm_country_point AS osm + SET "rank" = 6 + WHERE "rank" = 7; - -- TODO: This shouldn't be necessary? The rank function makes something wrong... - UPDATE osm_country_point AS osm - SET "rank" = 1 - WHERE "rank" = 0; + -- TODO: This shouldn't be necessary? The rank function makes something wrong... + UPDATE osm_country_point AS osm + SET "rank" = 1 + WHERE "rank" = 0; - UPDATE osm_country_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_country_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; @@ -82,38 +87,46 @@ $$ LANGUAGE plpgsql; SELECT update_osm_country_point(); -- ALTER TABLE osm_country_point ADD CONSTRAINT osm_country_point_rank_constraint CHECK("rank" BETWEEN 1 AND 6); -CREATE INDEX IF NOT EXISTS osm_country_point_rank_idx ON osm_country_point("rank"); +CREATE INDEX IF NOT EXISTS osm_country_point_rank_idx ON osm_country_point ("rank"); -- Handle updates CREATE SCHEMA IF NOT EXISTS place_country; -CREATE TABLE IF NOT EXISTS place_country.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION place_country.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS place_country.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION place_country.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO place_country.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO place_country.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION place_country.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh place_country rank'; PERFORM update_osm_country_point(); + -- noinspection SqlWithoutWhere DELETE FROM place_country.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_country_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_country_point FOR EACH STATEMENT - EXECUTE PROCEDURE place_country.flag(); +EXECUTE PROCEDURE place_country.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON place_country.updates + AFTER INSERT + ON place_country.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE place_country.refresh(); +EXECUTE PROCEDURE place_country.refresh(); diff --git a/layers/place/update_island_point.sql b/layers/place/update_island_point.sql index cedb646..b1c79f7 100644 --- a/layers/place/update_island_point.sql +++ b/layers/place/update_island_point.sql @@ -2,11 +2,12 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_island_point; DROP TRIGGER IF EXISTS trigger_refresh ON place_island_point.updates; -- etldoc: osm_island_point -> osm_island_point -CREATE OR REPLACE FUNCTION update_osm_island_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_island_point() RETURNS void AS +$$ BEGIN - UPDATE osm_island_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_island_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; @@ -17,32 +18,40 @@ SELECT update_osm_island_point(); CREATE SCHEMA IF NOT EXISTS place_island_point; -CREATE TABLE IF NOT EXISTS place_island_point.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION place_island_point.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS place_island_point.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION place_island_point.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO place_island_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO place_island_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION place_island_point.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh place_island_point'; PERFORM update_osm_island_point(); + -- noinspection SqlWithoutWhere DELETE FROM place_island_point.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_island_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_island_point FOR EACH STATEMENT - EXECUTE PROCEDURE place_island_point.flag(); +EXECUTE PROCEDURE place_island_point.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON place_island_point.updates + AFTER INSERT + ON place_island_point.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE place_island_point.refresh(); +EXECUTE PROCEDURE place_island_point.refresh(); diff --git a/layers/place/update_island_polygon.sql b/layers/place/update_island_polygon.sql index 29eebd3..9938373 100644 --- a/layers/place/update_island_polygon.sql +++ b/layers/place/update_island_polygon.sql @@ -2,15 +2,16 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_island_polygon; DROP TRIGGER IF EXISTS trigger_refresh ON place_island_polygon.updates; -- etldoc: osm_island_polygon -> osm_island_polygon -CREATE OR REPLACE FUNCTION update_osm_island_polygon() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_island_polygon() RETURNS void AS +$$ BEGIN - UPDATE osm_island_polygon SET geometry=ST_PointOnSurface(geometry) WHERE ST_GeometryType(geometry) <> 'ST_Point'; + UPDATE osm_island_polygon SET geometry=ST_PointOnSurface(geometry) WHERE ST_GeometryType(geometry) <> 'ST_Point'; - UPDATE osm_island_polygon - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_island_polygon + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; - ANALYZE osm_island_polygon; + ANALYZE osm_island_polygon; END; $$ LANGUAGE plpgsql; @@ -20,32 +21,40 @@ SELECT update_osm_island_polygon(); CREATE SCHEMA IF NOT EXISTS place_island_polygon; -CREATE TABLE IF NOT EXISTS place_island_polygon.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION place_island_polygon.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS place_island_polygon.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION place_island_polygon.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO place_island_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO place_island_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION place_island_polygon.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh place_island_polygon'; PERFORM update_osm_island_polygon(); + -- noinspection SqlWithoutWhere DELETE FROM place_island_polygon.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_island_polygon + AFTER INSERT OR UPDATE OR DELETE + ON osm_island_polygon FOR EACH STATEMENT - EXECUTE PROCEDURE place_island_polygon.flag(); +EXECUTE PROCEDURE place_island_polygon.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON place_island_polygon.updates + AFTER INSERT + ON place_island_polygon.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE place_island_polygon.refresh(); +EXECUTE PROCEDURE place_island_polygon.refresh(); diff --git a/layers/place/update_state_point.sql b/layers/place/update_state_point.sql index 878d6ad..4693d3c 100644 --- a/layers/place/update_state_point.sql +++ b/layers/place/update_state_point.sql @@ -1,40 +1,50 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_state_point; DROP TRIGGER IF EXISTS trigger_refresh ON place_state.updates; -ALTER TABLE osm_state_point DROP CONSTRAINT IF EXISTS osm_state_point_rank_constraint; +ALTER TABLE osm_state_point + DROP CONSTRAINT IF EXISTS osm_state_point_rank_constraint; -- etldoc: ne_10m_admin_1_states_provinces -> osm_state_point -- etldoc: osm_state_point -> osm_state_point -CREATE OR REPLACE FUNCTION update_osm_state_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_state_point() RETURNS void AS +$$ BEGIN - WITH important_state_point AS ( - SELECT osm.geometry, osm.osm_id, osm.name, COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en, ne.scalerank, ne.labelrank, ne.datarank - FROM ne_10m_admin_1_states_provinces AS ne, osm_state_point AS osm - WHERE - -- We only match whether the point is within the Natural Earth polygon - -- because name matching is difficult - ST_Within(osm.geometry, ne.geometry) - -- We leave out leess important states - AND ne.scalerank <= 3 AND ne.labelrank <= 2 - ) - UPDATE osm_state_point AS osm - -- Normalize both scalerank and labelrank into a ranking system from 1 to 6. - SET "rank" = LEAST(6, CEILING((scalerank + labelrank + datarank)/3.0)) - FROM important_state_point AS ne - WHERE osm.osm_id = ne.osm_id; + WITH important_state_point AS ( + SELECT osm.geometry, + osm.osm_id, + osm.name, + COALESCE(NULLIF(osm.name_en, ''), ne.name) AS name_en, + ne.scalerank, + ne.labelrank, + ne.datarank + FROM ne_10m_admin_1_states_provinces AS ne, + osm_state_point AS osm + WHERE + -- We only match whether the point is within the Natural Earth polygon + -- because name matching is difficult + ST_Within(osm.geometry, ne.geometry) + -- We leave out leess important states + AND ne.scalerank <= 3 + AND ne.labelrank <= 2 + ) + UPDATE osm_state_point AS osm + -- Normalize both scalerank and labelrank into a ranking system from 1 to 6. + SET "rank" = LEAST(6, CEILING((scalerank + labelrank + datarank) / 3.0)) + FROM important_state_point AS ne + WHERE osm.osm_id = ne.osm_id; - -- TODO: This shouldn't be necessary? The rank function makes something wrong... - UPDATE osm_state_point AS osm - SET "rank" = 1 - WHERE "rank" = 0; + -- TODO: This shouldn't be necessary? The rank function makes something wrong... + UPDATE osm_state_point AS osm + SET "rank" = 1 + WHERE "rank" = 0; - DELETE FROM osm_state_point WHERE "rank" IS NULL; + DELETE FROM osm_state_point WHERE "rank" IS NULL; - UPDATE osm_state_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_state_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; @@ -42,38 +52,46 @@ $$ LANGUAGE plpgsql; SELECT update_osm_state_point(); -- ALTER TABLE osm_state_point ADD CONSTRAINT osm_state_point_rank_constraint CHECK("rank" BETWEEN 1 AND 6); -CREATE INDEX IF NOT EXISTS osm_state_point_rank_idx ON osm_state_point("rank"); +CREATE INDEX IF NOT EXISTS osm_state_point_rank_idx ON osm_state_point ("rank"); -- Handle updates CREATE SCHEMA IF NOT EXISTS place_state; -CREATE TABLE IF NOT EXISTS place_state.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION place_state.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS place_state.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION place_state.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO place_state.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO place_state.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION place_state.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh place_state rank'; PERFORM update_osm_state_point(); + -- noinspection SqlWithoutWhere DELETE FROM place_state.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_state_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_state_point FOR EACH STATEMENT - EXECUTE PROCEDURE place_state.flag(); +EXECUTE PROCEDURE place_state.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON place_state.updates + AFTER INSERT + ON place_state.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE place_state.refresh(); +EXECUTE PROCEDURE place_state.refresh(); diff --git a/layers/poi/class.sql b/layers/poi/class.sql index eea2319..a36fbdf 100644 --- a/layers/poi/class.sql +++ b/layers/poi/class.sql @@ -1,40 +1,40 @@ -CREATE OR REPLACE FUNCTION poi_class_rank(class TEXT) -RETURNS INT AS $$ - SELECT CASE class - WHEN 'hospital' THEN 20 - WHEN 'railway' THEN 40 - WHEN 'bus' THEN 50 - WHEN 'attraction' THEN 70 - WHEN 'harbor' THEN 75 - WHEN 'college' THEN 80 - WHEN 'school' THEN 85 - WHEN 'stadium' THEN 90 - WHEN 'zoo' THEN 95 - WHEN 'town_hall' THEN 100 - WHEN 'campsite' THEN 110 - WHEN 'cemetery' THEN 115 - WHEN 'park' THEN 120 - WHEN 'library' THEN 130 - WHEN 'police' THEN 135 - WHEN 'post' THEN 140 - WHEN 'golf' THEN 150 - WHEN 'shop' THEN 400 - WHEN 'grocery' THEN 500 - WHEN 'fast_food' THEN 600 - WHEN 'clothing_store' THEN 700 - WHEN 'bar' THEN 800 - ELSE 1000 - END; +CREATE OR REPLACE FUNCTION poi_class_rank(class text) + RETURNS int AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT CASE class + WHEN 'hospital' THEN 20 + WHEN 'railway' THEN 40 + WHEN 'bus' THEN 50 + WHEN 'attraction' THEN 70 + WHEN 'harbor' THEN 75 + WHEN 'college' THEN 80 + WHEN 'school' THEN 85 + WHEN 'stadium' THEN 90 + WHEN 'zoo' THEN 95 + WHEN 'town_hall' THEN 100 + WHEN 'campsite' THEN 110 + WHEN 'cemetery' THEN 115 + WHEN 'park' THEN 120 + WHEN 'library' THEN 130 + WHEN 'police' THEN 135 + WHEN 'post' THEN 140 + WHEN 'golf' THEN 150 + WHEN 'shop' THEN 400 + WHEN 'grocery' THEN 500 + WHEN 'fast_food' THEN 600 + WHEN 'clothing_store' THEN 700 + WHEN 'bar' THEN 800 + ELSE 1000 + END; +$$ LANGUAGE SQL IMMUTABLE + PARALLEL SAFE; -CREATE OR REPLACE FUNCTION poi_class(subclass TEXT, mapping_key TEXT) -RETURNS TEXT AS $$ - SELECT CASE - %%FIELD_MAPPING: class %% - ELSE subclass - END; +CREATE OR REPLACE FUNCTION poi_class(subclass text, mapping_key text) + RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT CASE + %%FIELD_MAPPING: class %% + ELSE subclass + END; +$$ LANGUAGE SQL IMMUTABLE + PARALLEL SAFE; diff --git a/layers/poi/layer.sql b/layers/poi/layer.sql index 35c80e2..a268bc6 100644 --- a/layers/poi/layer.sql +++ b/layers/poi/layer.sql @@ -1,75 +1,99 @@ - -- etldoc: layer_poi[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_poi | z12 | z13 | z14+" ] ; CREATE OR REPLACE FUNCTION layer_poi(bbox geometry, zoom_level integer, pixel_width numeric) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, name_de text, tags hstore, class text, subclass text, agg_stop integer, layer integer, level integer, indoor integer, "rank" int) AS $$ - SELECT osm_id_hash AS osm_id, geometry, NULLIF(name, '') AS name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - poi_class(subclass, mapping_key) AS class, - CASE - WHEN subclass = 'information' - THEN NULLIF(information, '') - WHEN subclass = 'place_of_worship' - THEN NULLIF(religion, '') - WHEN subclass = 'pitch' - THEN NULLIF(sport, '') - ELSE subclass - END AS subclass, - agg_stop, - NULLIF(layer, 0) AS layer, - "level", - CASE WHEN indoor=TRUE THEN 1 END as indoor, - row_number() OVER ( - PARTITION BY LabelGrid(geometry, 100 * pixel_width) - ORDER BY CASE WHEN name = '' THEN 2000 ELSE poi_class_rank(poi_class(subclass, mapping_key)) END ASC - )::int AS "rank" - FROM ( - -- etldoc: osm_poi_point -> layer_poi:z12 - -- etldoc: osm_poi_point -> layer_poi:z13 - SELECT *, - osm_id*10 AS osm_id_hash FROM osm_poi_point - WHERE geometry && bbox - AND zoom_level BETWEEN 12 AND 13 - AND ((subclass='station' AND mapping_key = 'railway') - OR subclass IN ('halt', 'ferry_terminal')) - UNION ALL - - -- etldoc: osm_poi_point -> layer_poi:z14_ - SELECT *, - osm_id*10 AS osm_id_hash FROM osm_poi_point - WHERE geometry && bbox - AND zoom_level >= 14 - - UNION ALL - -- etldoc: osm_poi_polygon -> layer_poi:z12 - -- etldoc: osm_poi_polygon -> layer_poi:z13 - SELECT *, - NULL::INTEGER AS agg_stop, - CASE WHEN osm_id<0 THEN -osm_id*10+4 - ELSE osm_id*10+1 - END AS osm_id_hash - FROM osm_poi_polygon - WHERE geometry && bbox - AND zoom_level BETWEEN 12 AND 13 - AND ((subclass='station' AND mapping_key = 'railway') - OR subclass IN ('halt', 'ferry_terminal')) - - UNION ALL - -- etldoc: osm_poi_polygon -> layer_poi:z14_ - SELECT *, - NULL::INTEGER AS agg_stop, - CASE WHEN osm_id<0 THEN -osm_id*10+4 - ELSE osm_id*10+1 - END AS osm_id_hash - FROM osm_poi_polygon - WHERE geometry && bbox - AND zoom_level >= 14 - ) as poi_union - ORDER BY "rank" - ; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + tags hstore, + class text, + subclass text, + agg_stop integer, + layer integer, + level integer, + indoor integer, + "rank" int + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT osm_id_hash AS osm_id, + geometry, + NULLIF(name, '') AS name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + poi_class(subclass, mapping_key) AS class, + CASE + WHEN subclass = 'information' + THEN NULLIF(information, '') + WHEN subclass = 'place_of_worship' + THEN NULLIF(religion, '') + WHEN subclass = 'pitch' + THEN NULLIF(sport, '') + ELSE subclass + END AS subclass, + agg_stop, + NULLIF(layer, 0) AS layer, + "level", + CASE WHEN indoor = TRUE THEN 1 END AS indoor, + row_number() OVER ( + PARTITION BY LabelGrid(geometry, 100 * pixel_width) + ORDER BY CASE WHEN name = '' THEN 2000 ELSE poi_class_rank(poi_class(subclass, mapping_key)) END ASC + )::int AS "rank" +FROM ( + -- etldoc: osm_poi_point -> layer_poi:z12 + -- etldoc: osm_poi_point -> layer_poi:z13 + SELECT *, + osm_id * 10 AS osm_id_hash + FROM osm_poi_point + WHERE geometry && bbox + AND zoom_level BETWEEN 12 AND 13 + AND ((subclass = 'station' AND mapping_key = 'railway') + OR subclass IN ('halt', 'ferry_terminal')) + + UNION ALL + + -- etldoc: osm_poi_point -> layer_poi:z14_ + SELECT *, + osm_id * 10 AS osm_id_hash + FROM osm_poi_point + WHERE geometry && bbox + AND zoom_level >= 14 + + UNION ALL + + -- etldoc: osm_poi_polygon -> layer_poi:z12 + -- etldoc: osm_poi_polygon -> layer_poi:z13 + SELECT *, + NULL::integer AS agg_stop, + CASE + WHEN osm_id < 0 THEN -osm_id * 10 + 4 + ELSE osm_id * 10 + 1 + END AS osm_id_hash + FROM osm_poi_polygon + WHERE geometry && bbox + AND zoom_level BETWEEN 12 AND 13 + AND ((subclass = 'station' AND mapping_key = 'railway') + OR subclass IN ('halt', 'ferry_terminal')) + + UNION ALL + + -- etldoc: osm_poi_polygon -> layer_poi:z14_ + SELECT *, + NULL::integer AS agg_stop, + CASE + WHEN osm_id < 0 THEN -osm_id * 10 + 4 + ELSE osm_id * 10 + 1 + END AS osm_id_hash + FROM osm_poi_polygon + WHERE geometry && bbox + AND zoom_level >= 14 + ) AS poi_union +ORDER BY "rank" +$$ LANGUAGE SQL STABLE + PARALLEL SAFE; +-- TODO: Check if the above can be made STRICT -- i.e. if pixel_width could be NULL diff --git a/layers/poi/poi_stop_agg.sql b/layers/poi/poi_stop_agg.sql index 4e4f40a..3b1e905 100644 --- a/layers/poi/poi_stop_agg.sql +++ b/layers/poi/poi_stop_agg.sql @@ -1,35 +1,31 @@ DROP MATERIALIZED VIEW IF EXISTS osm_poi_stop_centroid CASCADE; -CREATE MATERIALIZED VIEW osm_poi_stop_centroid AS ( - SELECT - uic_ref, - count(*) as count, - CASE WHEN count(*) > 2 THEN ST_Centroid(ST_UNION(geometry)) END AS centroid - FROM osm_poi_point - WHERE - nullif(uic_ref, '') IS NOT NULL - AND subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') - GROUP BY - uic_ref - HAVING - count(*) > 1 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE MATERIALIZED VIEW osm_poi_stop_centroid AS +( +SELECT uic_ref, + count(*) AS count, + CASE WHEN count(*) > 2 THEN ST_Centroid(ST_UNION(geometry)) END AS centroid +FROM osm_poi_point +WHERE nullif(uic_ref, '') IS NOT NULL + AND subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') +GROUP BY uic_ref +HAVING count(*) > 1 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; DROP MATERIALIZED VIEW IF EXISTS osm_poi_stop_rank CASCADE; -CREATE MATERIALIZED VIEW osm_poi_stop_rank AS ( - SELECT - p.osm_id, +CREATE MATERIALIZED VIEW osm_poi_stop_rank AS +( +SELECT p.osm_id, -- p.uic_ref, -- p.subclass, - ROW_NUMBER() - OVER ( - PARTITION BY p.uic_ref - ORDER BY - p.subclass :: public_transport_stop_type NULLS LAST, - ST_Distance(c.centroid, p.geometry) - ) AS rk - FROM osm_poi_point p - INNER JOIN osm_poi_stop_centroid c ON (p.uic_ref = c.uic_ref) - WHERE - subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') - ORDER BY p.uic_ref, rk -) /* DELAY_MATERIALIZED_VIEW_CREATION */; + ROW_NUMBER() + OVER ( + PARTITION BY p.uic_ref + ORDER BY + p.subclass :: public_transport_stop_type NULLS LAST, + ST_Distance(c.centroid, p.geometry) + ) AS rk +FROM osm_poi_point p + INNER JOIN osm_poi_stop_centroid c ON (p.uic_ref = c.uic_ref) +WHERE subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') +ORDER BY p.uic_ref, rk + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; diff --git a/layers/poi/public_transport_stop_type.sql b/layers/poi/public_transport_stop_type.sql index 433aa17..fa37541 100644 --- a/layers/poi/public_transport_stop_type.sql +++ b/layers/poi/public_transport_stop_type.sql @@ -1,11 +1,12 @@ -DO $$ -BEGIN - IF NOT EXISTS (SELECT 1 - FROM pg_type - WHERE typname = 'public_transport_stop_type') THEN - CREATE TYPE public_transport_stop_type AS ENUM ( - 'subway', 'tram_stop', 'bus_station', 'bus_stop' - ); - END IF; -END +DO +$$ + BEGIN + IF NOT EXISTS(SELECT 1 + FROM pg_type + WHERE typname = 'public_transport_stop_type') THEN + CREATE TYPE public_transport_stop_type AS enum ( + 'subway', 'tram_stop', 'bus_station', 'bus_stop' + ); + END IF; + END $$; diff --git a/layers/poi/update_poi_point.sql b/layers/poi/update_poi_point.sql index bd6aeb4..d058b58 100644 --- a/layers/poi/update_poi_point.sql +++ b/layers/poi/update_poi_point.sql @@ -2,83 +2,95 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_poi_point; DROP TRIGGER IF EXISTS trigger_refresh ON poi_point.updates; -- etldoc: osm_poi_point -> osm_poi_point -CREATE OR REPLACE FUNCTION update_osm_poi_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_poi_point() RETURNS void AS +$$ BEGIN - UPDATE osm_poi_point + UPDATE osm_poi_point SET subclass = 'subway' - WHERE station = 'subway' and subclass='station'; + WHERE station = 'subway' + AND subclass = 'station'; - UPDATE osm_poi_point + UPDATE osm_poi_point SET subclass = 'halt' - WHERE funicular = 'yes' and subclass='station'; + WHERE funicular = 'yes' + AND subclass = 'station'; - UPDATE osm_poi_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_poi_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; SELECT update_osm_poi_point(); -CREATE OR REPLACE FUNCTION update_osm_poi_point_agg() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_poi_point_agg() RETURNS void AS +$$ BEGIN - UPDATE osm_poi_point p - SET agg_stop = CASE - WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') - THEN 1 - END; + UPDATE osm_poi_point p + SET agg_stop = CASE + WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') + THEN 1 + END; - UPDATE osm_poi_point p + UPDATE osm_poi_point p SET agg_stop = ( - CASE - WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') - AND r.rk IS NULL OR r.rk = 1 - THEN 1 - END) + CASE + WHEN p.subclass IN ('bus_stop', 'bus_station', 'tram_stop', 'subway') + AND r.rk IS NULL OR r.rk = 1 + THEN 1 + END) FROM osm_poi_stop_rank r - WHERE p.osm_id = r.osm_id - ; + WHERE p.osm_id = r.osm_id; END; $$ LANGUAGE plpgsql; -ALTER TABLE osm_poi_point ADD COLUMN IF NOT EXISTS agg_stop INTEGER DEFAULT NULL; +ALTER TABLE osm_poi_point + ADD COLUMN IF NOT EXISTS agg_stop integer DEFAULT NULL; SELECT update_osm_poi_point_agg(); -- Handle updates CREATE SCHEMA IF NOT EXISTS poi_point; -CREATE TABLE IF NOT EXISTS poi_point.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION poi_point.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS poi_point.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION poi_point.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO poi_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO poi_point.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION poi_point.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh poi_point'; PERFORM update_osm_poi_point(); REFRESH MATERIALIZED VIEW osm_poi_stop_centroid; REFRESH MATERIALIZED VIEW osm_poi_stop_rank; PERFORM update_osm_poi_point_agg(); + -- noinspection SqlWithoutWhere DELETE FROM poi_point.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_poi_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_poi_point FOR EACH STATEMENT - EXECUTE PROCEDURE poi_point.flag(); +EXECUTE PROCEDURE poi_point.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON poi_point.updates + AFTER INSERT + ON poi_point.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE poi_point.refresh(); +EXECUTE PROCEDURE poi_point.refresh(); diff --git a/layers/poi/update_poi_polygon.sql b/layers/poi/update_poi_polygon.sql index ff6061d..d1b042f 100644 --- a/layers/poi/update_poi_polygon.sql +++ b/layers/poi/update_poi_polygon.sql @@ -3,29 +3,33 @@ DROP TRIGGER IF EXISTS trigger_refresh ON poi_polygon.updates; -- etldoc: osm_poi_polygon -> osm_poi_polygon -CREATE OR REPLACE FUNCTION update_poi_polygon() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_poi_polygon() RETURNS void AS +$$ BEGIN - UPDATE osm_poi_polygon - SET geometry = - CASE WHEN ST_NPoints(ST_ConvexHull(geometry))=ST_NPoints(geometry) - THEN ST_Centroid(geometry) - ELSE ST_PointOnSurface(geometry) - END - WHERE ST_GeometryType(geometry) <> 'ST_Point'; + UPDATE osm_poi_polygon + SET geometry = + CASE + WHEN ST_NPoints(ST_ConvexHull(geometry)) = ST_NPoints(geometry) + THEN ST_Centroid(geometry) + ELSE ST_PointOnSurface(geometry) + END + WHERE ST_GeometryType(geometry) <> 'ST_Point'; - UPDATE osm_poi_polygon - SET subclass = 'subway' - WHERE station = 'subway' and subclass='station'; + UPDATE osm_poi_polygon + SET subclass = 'subway' + WHERE station = 'subway' + AND subclass = 'station'; - UPDATE osm_poi_polygon + UPDATE osm_poi_polygon SET subclass = 'halt' - WHERE funicular = 'yes' and subclass='station'; + WHERE funicular = 'yes' + AND subclass = 'station'; - UPDATE osm_poi_polygon - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_poi_polygon + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; - ANALYZE osm_poi_polygon; + ANALYZE osm_poi_polygon; END; $$ LANGUAGE plpgsql; @@ -35,32 +39,40 @@ SELECT update_poi_polygon(); CREATE SCHEMA IF NOT EXISTS poi_polygon; -CREATE TABLE IF NOT EXISTS poi_polygon.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION poi_polygon.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS poi_polygon.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION poi_polygon.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO poi_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO poi_polygon.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION poi_polygon.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh poi_polygon'; PERFORM update_poi_polygon(); + -- noinspection SqlWithoutWhere DELETE FROM poi_polygon.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_poi_polygon + AFTER INSERT OR UPDATE OR DELETE + ON osm_poi_polygon FOR EACH STATEMENT - EXECUTE PROCEDURE poi_polygon.flag(); +EXECUTE PROCEDURE poi_polygon.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON poi_polygon.updates + AFTER INSERT + ON poi_polygon.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE poi_polygon.refresh(); +EXECUTE PROCEDURE poi_polygon.refresh(); diff --git a/layers/transportation/class.sql b/layers/transportation/class.sql index 43642ba..5777a05 100644 --- a/layers/transportation/class.sql +++ b/layers/transportation/class.sql @@ -1,51 +1,58 @@ -CREATE OR REPLACE FUNCTION brunnel(is_bridge BOOL, is_tunnel BOOL, is_ford BOOL) RETURNS TEXT AS $$ - SELECT CASE - WHEN is_bridge THEN 'bridge' - WHEN is_tunnel THEN 'tunnel' - WHEN is_ford THEN 'ford' - END; +CREATE OR REPLACE FUNCTION brunnel(is_bridge bool, is_tunnel bool, is_ford bool) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN is_bridge THEN 'bridge' + WHEN is_tunnel THEN 'tunnel' + WHEN is_ford THEN 'ford' + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; -- The classes for highways are derived from the classes used in ClearTables -- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua -CREATE OR REPLACE FUNCTION highway_class(highway TEXT, public_transport TEXT, construction TEXT) RETURNS TEXT AS $$ - SELECT CASE - %%FIELD_MAPPING: class %% - END; +CREATE OR REPLACE FUNCTION highway_class(highway text, public_transport text, construction text) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT CASE + %%FIELD_MAPPING: class %% + END; +$$ LANGUAGE SQL IMMUTABLE + PARALLEL SAFE; -- The classes for railways are derived from the classes used in ClearTables -- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua -CREATE OR REPLACE FUNCTION railway_class(railway TEXT) RETURNS TEXT AS $$ - SELECT CASE - WHEN railway IN ('rail', 'narrow_gauge', 'preserved', 'funicular') THEN 'rail' - WHEN railway IN ('subway', 'light_rail', 'monorail', 'tram') THEN 'transit' - END; +CREATE OR REPLACE FUNCTION railway_class(railway text) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN railway IN ('rail', 'narrow_gauge', 'preserved', 'funicular') THEN 'rail' + WHEN railway IN ('subway', 'light_rail', 'monorail', 'tram') THEN 'transit' + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; -- Limit service to only the most important values to ensure -- we always know the values of service -CREATE OR REPLACE FUNCTION service_value(service TEXT) RETURNS TEXT AS $$ - SELECT CASE - WHEN service IN ('spur', 'yard', 'siding', 'crossover', 'driveway', 'alley', 'parking_aisle') THEN service - END; +CREATE OR REPLACE FUNCTION service_value(service text) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN service IN ('spur', 'yard', 'siding', 'crossover', 'driveway', 'alley', 'parking_aisle') THEN service + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; -- Limit surface to only the most important values to ensure -- we always know the values of surface -CREATE OR REPLACE FUNCTION surface_value(surface TEXT) RETURNS TEXT AS $$ - SELECT CASE - WHEN surface IN ('paved', 'asphalt', 'cobblestone', 'concrete', 'concrete:lanes', 'concrete:plates', 'metal', 'paving_stones', 'sett', 'unhewn_cobblestone', 'wood') THEN 'paved' - WHEN surface IN ('unpaved', 'compacted', 'dirt', 'earth', 'fine_gravel', 'grass', 'grass_paver', 'gravel', 'gravel_turf', 'ground', 'ice', 'mud', 'pebblestone', 'salt', 'sand', 'snow', 'woodchips') THEN 'unpaved' - END; +CREATE OR REPLACE FUNCTION surface_value(surface text) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN surface IN ('paved', 'asphalt', 'cobblestone', 'concrete', 'concrete:lanes', 'concrete:plates', 'metal', + 'paving_stones', 'sett', 'unhewn_cobblestone', 'wood') THEN 'paved' + WHEN surface IN ('unpaved', 'compacted', 'dirt', 'earth', 'fine_gravel', 'grass', 'grass_paver', 'gravel', + 'gravel_turf', 'ground', 'ice', 'mud', 'pebblestone', 'salt', 'sand', 'snow', 'woodchips') + THEN 'unpaved' + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; diff --git a/layers/transportation/layer.sql b/layers/transportation/layer.sql index 4b8bd88..31966b3 100644 --- a/layers/transportation/layer.sql +++ b/layers/transportation/layer.sql @@ -1,373 +1,703 @@ -CREATE OR REPLACE FUNCTION highway_is_link(highway TEXT) RETURNS BOOLEAN AS $$ - SELECT highway LIKE '%_link'; +CREATE OR REPLACE FUNCTION highway_is_link(highway text) RETURNS boolean AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT highway LIKE '%_link'; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; -- etldoc: layer_transportation[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label=" layer_transportation | z4 | z5 | z6 | z7 | z8 | z9 | z10 | z11 | z12| z13| z14+" ] ; CREATE OR REPLACE FUNCTION layer_transportation(bbox geometry, zoom_level int) -RETURNS TABLE(osm_id bigint, geometry geometry, class text, subclass text, -ramp int, oneway int, brunnel TEXT, service TEXT, layer INT, level INT, -indoor INT, bicycle TEXT, foot TEXT, horse TEXT, mtb_scale TEXT, surface TEXT) AS $$ - SELECT - osm_id, geometry, - CASE - WHEN NULLIF(highway, '') IS NOT NULL OR NULLIF(public_transport, '') IS NOT NULL THEN highway_class(highway, public_transport, construction) - WHEN NULLIF(railway, '') IS NOT NULL THEN railway_class(railway) - WHEN NULLIF(aerialway, '') IS NOT NULL THEN aerialway - WHEN NULLIF(shipway, '') IS NOT NULL THEN shipway - WHEN NULLIF(man_made, '') IS NOT NULL THEN man_made - END AS class, - CASE - WHEN railway IS NOT NULL THEN railway - WHEN (highway IS NOT NULL OR public_transport IS NOT NULL) - AND highway_class(highway, public_transport, construction) = 'path' - THEN COALESCE(NULLIF(public_transport, ''), highway) - END AS subclass, - -- All links are considered as ramps as well - CASE WHEN highway_is_link(highway) OR highway = 'steps' - THEN 1 ELSE is_ramp::int END AS ramp, - is_oneway::int AS oneway, - brunnel(is_bridge, is_tunnel, is_ford) AS brunnel, - NULLIF(service, '') AS service, - NULLIF(layer, 0) AS layer, - "level", - CASE WHEN indoor=TRUE THEN 1 END as indoor, - NULLIF(bicycle, '') AS bicycle, - NULLIF(foot, '') AS foot, - NULLIF(horse, '') AS horse, - NULLIF(mtb_scale, '') AS mtb_scale, - NULLIF(surface, '') AS surface - FROM ( - -- etldoc: osm_transportation_merge_linestring_gen7 -> layer_transportation:z4 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_transportation_merge_linestring_gen7 - WHERE zoom_level = 4 - UNION ALL - - -- etldoc: osm_transportation_merge_linestring_gen6 -> layer_transportation:z5 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_transportation_merge_linestring_gen6 - WHERE zoom_level = 5 - UNION ALL - - -- etldoc: osm_transportation_merge_linestring_gen5 -> layer_transportation:z6 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_transportation_merge_linestring_gen5 - WHERE zoom_level = 6 - UNION ALL - - -- etldoc: osm_transportation_merge_linestring_gen4 -> layer_transportation:z7 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_transportation_merge_linestring_gen4 - WHERE zoom_level = 7 - UNION ALL - - -- etldoc: osm_transportation_merge_linestring_gen3 -> layer_transportation:z8 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_transportation_merge_linestring_gen3 - WHERE zoom_level = 8 - UNION ALL - - -- etldoc: osm_highway_linestring_gen2 -> layer_transportation:z9 - -- etldoc: osm_highway_linestring_gen2 -> layer_transportation:z10 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - bicycle, foot, horse, mtb_scale, - NULL AS surface, z_order - FROM osm_highway_linestring_gen2 - WHERE zoom_level BETWEEN 9 AND 10 - AND st_length(geometry)>zres(11) - UNION ALL - - -- etldoc: osm_highway_linestring_gen1 -> layer_transportation:z11 - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, NULL AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - bicycle, foot, horse, mtb_scale, - NULL AS surface, z_order - FROM osm_highway_linestring_gen1 - WHERE zoom_level = 11 - AND st_length(geometry)>zres(12) - UNION ALL - - -- etldoc: osm_highway_linestring -> layer_transportation:z12 - -- etldoc: osm_highway_linestring -> layer_transportation:z13 - -- etldoc: osm_highway_linestring -> layer_transportation:z14_ - SELECT - osm_id, geometry, - highway, construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, man_made, - layer, - CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level", - CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor, - bicycle, foot, horse, mtb_scale, - surface_value(surface) AS "surface", - z_order - FROM osm_highway_linestring - WHERE NOT is_area AND ( - zoom_level = 12 AND ( - highway_class(highway, public_transport, construction) NOT IN ('track', 'path', 'minor') - OR highway IN ('unclassified', 'residential') - ) AND man_made <> 'pier' - OR zoom_level = 13 - AND ( - highway_class(highway, public_transport, construction) NOT IN ('track', 'path') AND man_made <> 'pier' - OR - man_made = 'pier' AND NOT ST_IsClosed(geometry) - ) - OR zoom_level >= 14 - AND ( - man_made <> 'pier' - OR - NOT ST_IsClosed(geometry) - ) - ) - UNION ALL - - -- etldoc: osm_railway_linestring_gen5 -> layer_transportation:z8 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL as surface, z_order - FROM osm_railway_linestring_gen5 - WHERE zoom_level = 8 - AND railway='rail' AND service = '' and usage='main' - UNION ALL - - -- etldoc: osm_railway_linestring_gen4 -> layer_transportation:z9 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, - NULL::boolean AS is_ford, - NULL::boolean AS is_ramp, NULL::int AS is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_railway_linestring_gen4 - WHERE zoom_level = 9 - AND railway='rail' AND service = '' and usage='main' - UNION ALL - - -- etldoc: osm_railway_linestring_gen3 -> layer_transportation:z10 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_railway_linestring_gen3 - WHERE zoom_level = 10 - AND railway IN ('rail', 'narrow_gauge') AND service = '' - UNION ALL - - -- etldoc: osm_railway_linestring_gen2 -> layer_transportation:z11 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL as surface, z_order - FROM osm_railway_linestring_gen2 - WHERE zoom_level = 11 - AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = '' - UNION ALL - - -- etldoc: osm_railway_linestring_gen1 -> layer_transportation:z12 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL as surface, z_order - FROM osm_railway_linestring_gen1 - WHERE zoom_level = 12 - AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = '' - UNION ALL - - -- etldoc: osm_railway_linestring -> layer_transportation:z13 - -- etldoc: osm_railway_linestring -> layer_transportation:z14_ - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, railway, NULL AS aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL as surface, z_order - FROM osm_railway_linestring - WHERE zoom_level = 13 - AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = '' - OR zoom_Level >= 14 - UNION ALL - - -- etldoc: osm_aerialway_linestring_gen1 -> layer_transportation:z12 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, NULL as railway, aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_aerialway_linestring_gen1 - WHERE zoom_level = 12 - UNION ALL - - -- etldoc: osm_aerialway_linestring -> layer_transportation:z13 - -- etldoc: osm_aerialway_linestring -> layer_transportation:z14_ - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, NULL as railway, aerialway, NULL AS shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_aerialway_linestring - WHERE zoom_level >= 13 - UNION ALL - - -- etldoc: osm_shipway_linestring_gen2 -> layer_transportation:z11 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, NULL AS railway, NULL AS aerialway, shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_shipway_linestring_gen2 - WHERE zoom_level = 11 - UNION ALL - - -- etldoc: osm_shipway_linestring_gen1 -> layer_transportation:z12 - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, NULL AS railway, NULL AS aerialway, shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_shipway_linestring_gen1 - WHERE zoom_level = 12 - UNION ALL - - -- etldoc: osm_shipway_linestring -> layer_transportation:z13 - -- etldoc: osm_shipway_linestring -> layer_transportation:z14_ - SELECT - osm_id, geometry, - NULL AS highway, NULL AS construction, NULL AS railway, NULL AS aerialway, shipway, - NULL AS public_transport, service_value(service) AS service, - is_bridge, is_tunnel, is_ford, is_ramp, is_oneway, NULL as man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_shipway_linestring - WHERE zoom_level >= 13 - UNION ALL - - -- NOTE: We limit the selection of polys because we need to be - -- careful to net get false positives here because - -- it is possible that closed linestrings appear both as - -- highway linestrings and as polygon - -- etldoc: osm_highway_polygon -> layer_transportation:z13 - -- etldoc: osm_highway_polygon -> layer_transportation:z14_ - SELECT - osm_id, geometry, - highway, NULL AS construction, NULL AS railway, NULL AS aerialway, NULL AS shipway, - public_transport, NULL AS service, - CASE WHEN man_made IN ('bridge') THEN TRUE - ELSE FALSE - END AS is_bridge, FALSE AS is_tunnel, FALSE AS is_ford, - FALSE AS is_ramp, FALSE::int AS is_oneway, man_made, - layer, NULL::int AS level, NULL::boolean AS indoor, - NULL as bicycle, NULL as foot, NULL as horse, NULL as mtb_scale, - NULL AS surface, z_order - FROM osm_highway_polygon - -- We do not want underground pedestrian areas for now - WHERE zoom_level >= 13 - AND ( - man_made IN ('bridge', 'pier') - OR (is_area AND COALESCE(layer, 0) >= 0) + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + class text, + subclass text, + ramp int, + oneway int, + brunnel text, + service text, + layer int, + level int, + indoor int, + bicycle text, + foot text, + horse text, + mtb_scale text, + surface text ) - ) AS zoom_levels - WHERE geometry && bbox - ORDER BY z_order ASC; +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT osm_id, + geometry, + CASE + WHEN NULLIF(highway, '') IS NOT NULL OR NULLIF(public_transport, '') IS NOT NULL + THEN highway_class(highway, public_transport, construction) + WHEN NULLIF(railway, '') IS NOT NULL THEN railway_class(railway) + WHEN NULLIF(aerialway, '') IS NOT NULL THEN aerialway + WHEN NULLIF(shipway, '') IS NOT NULL THEN shipway + WHEN NULLIF(man_made, '') IS NOT NULL THEN man_made + END AS class, + CASE + WHEN railway IS NOT NULL THEN railway + WHEN (highway IS NOT NULL OR public_transport IS NOT NULL) + AND highway_class(highway, public_transport, construction) = 'path' + THEN COALESCE(NULLIF(public_transport, ''), highway) + END AS subclass, + -- All links are considered as ramps as well + CASE + WHEN highway_is_link(highway) OR highway = 'steps' + THEN 1 + ELSE is_ramp::int END AS ramp, + is_oneway::int AS oneway, + brunnel(is_bridge, is_tunnel, is_ford) AS brunnel, + NULLIF(service, '') AS service, + NULLIF(layer, 0) AS layer, + "level", + CASE WHEN indoor = TRUE THEN 1 END AS indoor, + NULLIF(bicycle, '') AS bicycle, + NULLIF(foot, '') AS foot, + NULLIF(horse, '') AS horse, + NULLIF(mtb_scale, '') AS mtb_scale, + NULLIF(surface, '') AS surface +FROM ( + -- etldoc: osm_transportation_merge_linestring_gen7 -> layer_transportation:z4 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_transportation_merge_linestring_gen7 + WHERE zoom_level = 4 + UNION ALL + + -- etldoc: osm_transportation_merge_linestring_gen6 -> layer_transportation:z5 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_transportation_merge_linestring_gen6 + WHERE zoom_level = 5 + UNION ALL + + -- etldoc: osm_transportation_merge_linestring_gen5 -> layer_transportation:z6 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_transportation_merge_linestring_gen5 + WHERE zoom_level = 6 + UNION ALL + + -- etldoc: osm_transportation_merge_linestring_gen4 -> layer_transportation:z7 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_transportation_merge_linestring_gen4 + WHERE zoom_level = 7 + UNION ALL + + -- etldoc: osm_transportation_merge_linestring_gen3 -> layer_transportation:z8 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_transportation_merge_linestring_gen3 + WHERE zoom_level = 8 + UNION ALL + + -- etldoc: osm_highway_linestring_gen2 -> layer_transportation:z9 + -- etldoc: osm_highway_linestring_gen2 -> layer_transportation:z10 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + bicycle, + foot, + horse, + mtb_scale, + NULL AS surface, + z_order + FROM osm_highway_linestring_gen2 + WHERE zoom_level BETWEEN 9 AND 10 + AND st_length(geometry) > zres(11) + UNION ALL + + -- etldoc: osm_highway_linestring_gen1 -> layer_transportation:z11 + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + NULL AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + bicycle, + foot, + horse, + mtb_scale, + NULL AS surface, + z_order + FROM osm_highway_linestring_gen1 + WHERE zoom_level = 11 + AND st_length(geometry) > zres(12) + UNION ALL + + -- etldoc: osm_highway_linestring -> layer_transportation:z12 + -- etldoc: osm_highway_linestring -> layer_transportation:z13 + -- etldoc: osm_highway_linestring -> layer_transportation:z14_ + SELECT osm_id, + geometry, + highway, + construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + man_made, + layer, + CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level", + CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor, + bicycle, + foot, + horse, + mtb_scale, + surface_value(surface) AS "surface", + z_order + FROM osm_highway_linestring + WHERE NOT is_area + AND ( + zoom_level = 12 AND ( + highway_class(highway, public_transport, construction) NOT IN ('track', 'path', 'minor') + OR highway IN ('unclassified', 'residential') + ) AND man_made <> 'pier' + OR zoom_level = 13 + AND ( + highway_class(highway, public_transport, construction) NOT IN ('track', 'path') AND + man_made <> 'pier' + OR + man_made = 'pier' AND NOT ST_IsClosed(geometry) + ) + OR zoom_level >= 14 + AND ( + man_made <> 'pier' + OR + NOT ST_IsClosed(geometry) + ) + ) + UNION ALL + + -- etldoc: osm_railway_linestring_gen5 -> layer_transportation:z8 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_railway_linestring_gen5 + WHERE zoom_level = 8 + AND railway = 'rail' + AND service = '' + AND usage = 'main' + UNION ALL + + -- etldoc: osm_railway_linestring_gen4 -> layer_transportation:z9 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_ford, + NULL::boolean AS is_ramp, + NULL::int AS is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_railway_linestring_gen4 + WHERE zoom_level = 9 + AND railway = 'rail' + AND service = '' + AND usage = 'main' + UNION ALL + + -- etldoc: osm_railway_linestring_gen3 -> layer_transportation:z10 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_railway_linestring_gen3 + WHERE zoom_level = 10 + AND railway IN ('rail', 'narrow_gauge') + AND service = '' + UNION ALL + + -- etldoc: osm_railway_linestring_gen2 -> layer_transportation:z11 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_railway_linestring_gen2 + WHERE zoom_level = 11 + AND railway IN ('rail', 'narrow_gauge', 'light_rail') + AND service = '' + UNION ALL + + -- etldoc: osm_railway_linestring_gen1 -> layer_transportation:z12 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_railway_linestring_gen1 + WHERE zoom_level = 12 + AND railway IN ('rail', 'narrow_gauge', 'light_rail') + AND service = '' + UNION ALL + + -- etldoc: osm_railway_linestring -> layer_transportation:z13 + -- etldoc: osm_railway_linestring -> layer_transportation:z14_ + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + railway, + NULL AS aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_railway_linestring + WHERE zoom_level = 13 + AND railway IN ('rail', 'narrow_gauge', 'light_rail') AND service = '' + OR zoom_level >= 14 + UNION ALL + + -- etldoc: osm_aerialway_linestring_gen1 -> layer_transportation:z12 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + NULL AS railway, + aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_aerialway_linestring_gen1 + WHERE zoom_level = 12 + UNION ALL + + -- etldoc: osm_aerialway_linestring -> layer_transportation:z13 + -- etldoc: osm_aerialway_linestring -> layer_transportation:z14_ + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + NULL AS railway, + aerialway, + NULL AS shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_aerialway_linestring + WHERE zoom_level >= 13 + UNION ALL + + -- etldoc: osm_shipway_linestring_gen2 -> layer_transportation:z11 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + NULL AS railway, + NULL AS aerialway, + shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_shipway_linestring_gen2 + WHERE zoom_level = 11 + UNION ALL + + -- etldoc: osm_shipway_linestring_gen1 -> layer_transportation:z12 + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + NULL AS railway, + NULL AS aerialway, + shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_shipway_linestring_gen1 + WHERE zoom_level = 12 + UNION ALL + + -- etldoc: osm_shipway_linestring -> layer_transportation:z13 + -- etldoc: osm_shipway_linestring -> layer_transportation:z14_ + SELECT osm_id, + geometry, + NULL AS highway, + NULL AS construction, + NULL AS railway, + NULL AS aerialway, + shipway, + NULL AS public_transport, + service_value(service) AS service, + is_bridge, + is_tunnel, + is_ford, + is_ramp, + is_oneway, + NULL AS man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_shipway_linestring + WHERE zoom_level >= 13 + UNION ALL + + -- NOTE: We limit the selection of polys because we need to be + -- careful to net get false positives here because + -- it is possible that closed linestrings appear both as + -- highway linestrings and as polygon + -- etldoc: osm_highway_polygon -> layer_transportation:z13 + -- etldoc: osm_highway_polygon -> layer_transportation:z14_ + SELECT osm_id, + geometry, + highway, + NULL AS construction, + NULL AS railway, + NULL AS aerialway, + NULL AS shipway, + public_transport, + NULL AS service, + CASE + WHEN man_made IN ('bridge') THEN TRUE + ELSE FALSE + END AS is_bridge, + FALSE AS is_tunnel, + FALSE AS is_ford, + FALSE AS is_ramp, + FALSE::int AS is_oneway, + man_made, + layer, + NULL::int AS level, + NULL::boolean AS indoor, + NULL AS bicycle, + NULL AS foot, + NULL AS horse, + NULL AS mtb_scale, + NULL AS surface, + z_order + FROM osm_highway_polygon + -- We do not want underground pedestrian areas for now + WHERE zoom_level >= 13 + AND ( + man_made IN ('bridge', 'pier') + OR (is_area AND COALESCE(layer, 0) >= 0) + ) + ) AS zoom_levels +WHERE geometry && bbox +ORDER BY z_order ASC; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/transportation/update_transportation_merge.sql b/layers/transportation/update_transportation_merge.sql index 4c21900..962b1b5 100644 --- a/layers/transportation/update_transportation_merge.sql +++ b/layers/transportation/update_transportation_merge.sql @@ -17,113 +17,129 @@ DROP TRIGGER IF EXISTS trigger_refresh ON transportation.updates; -- Improve performance of the sql in transportation_name/network_type.sql CREATE INDEX IF NOT EXISTS osm_highway_linestring_highway_idx - ON osm_highway_linestring(highway); + ON osm_highway_linestring (highway); -- Improve performance of the sql below CREATE INDEX IF NOT EXISTS osm_highway_linestring_highway_partial_idx - ON osm_highway_linestring(highway) - WHERE highway IN ('motorway','trunk', 'primary', 'construction'); + ON osm_highway_linestring (highway) + WHERE highway IN ('motorway', 'trunk', 'primary', 'construction'); - -- etldoc: osm_highway_linestring -> osm_transportation_merge_linestring -CREATE MATERIALIZED VIEW osm_transportation_merge_linestring AS ( - SELECT - (ST_Dump(geometry)).geom AS geometry, - NULL::bigint AS osm_id, - highway, construction, - z_order - FROM ( - SELECT - ST_LineMerge(ST_Collect(geometry)) AS geometry, - highway, construction, - min(z_order) AS z_order - FROM osm_highway_linestring - WHERE (highway IN ('motorway','trunk', 'primary') OR highway = 'construction' AND construction IN ('motorway','trunk', 'primary')) - AND ST_IsValid(geometry) - group by highway, construction - ) AS highway_union -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +-- etldoc: osm_highway_linestring -> osm_transportation_merge_linestring +CREATE MATERIALIZED VIEW osm_transportation_merge_linestring AS +( +SELECT (ST_Dump(geometry)).geom AS geometry, + NULL::bigint AS osm_id, + highway, + construction, + z_order +FROM ( + SELECT ST_LineMerge(ST_Collect(geometry)) AS geometry, + highway, + construction, + min(z_order) AS z_order + FROM osm_highway_linestring + WHERE (highway IN ('motorway', 'trunk', 'primary') OR + highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary')) + AND ST_IsValid(geometry) + GROUP BY highway, construction + ) AS highway_union + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_geometry_idx - ON osm_transportation_merge_linestring USING gist(geometry); + ON osm_transportation_merge_linestring USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_highway_partial_idx - ON osm_transportation_merge_linestring(highway, construction) - WHERE highway IN ('motorway','trunk', 'primary', 'construction'); + ON osm_transportation_merge_linestring (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'primary', 'construction'); -- etldoc: osm_transportation_merge_linestring -> osm_transportation_merge_linestring_gen3 -CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen3 AS ( - SELECT ST_Simplify(geometry, 120) AS geometry, osm_id, highway, construction, z_order - FROM osm_transportation_merge_linestring - WHERE highway IN ('motorway','trunk', 'primary') - OR highway = 'construction' AND construction IN ('motorway','trunk', 'primary') -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen3 AS +( +SELECT ST_Simplify(geometry, 120) AS geometry, osm_id, highway, construction, z_order +FROM osm_transportation_merge_linestring +WHERE highway IN ('motorway', 'trunk', 'primary') + OR highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary') + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen3_geometry_idx - ON osm_transportation_merge_linestring_gen3 USING gist(geometry); + ON osm_transportation_merge_linestring_gen3 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen3_highway_partial_idx - ON osm_transportation_merge_linestring_gen3(highway, construction) - WHERE highway IN ('motorway','trunk', 'primary', 'construction'); + ON osm_transportation_merge_linestring_gen3 (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'primary', 'construction'); -- etldoc: osm_transportation_merge_linestring_gen3 -> osm_transportation_merge_linestring_gen4 -CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen4 AS ( - SELECT ST_Simplify(geometry, 200) AS geometry, osm_id, highway, construction, z_order - FROM osm_transportation_merge_linestring_gen3 - WHERE (highway IN ('motorway','trunk', 'primary') OR highway = 'construction' AND construction IN ('motorway','trunk', 'primary')) - AND ST_Length(geometry) > 50 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen4 AS +( +SELECT ST_Simplify(geometry, 200) AS geometry, osm_id, highway, construction, z_order +FROM osm_transportation_merge_linestring_gen3 +WHERE (highway IN ('motorway', 'trunk', 'primary') OR + highway = 'construction' AND construction IN ('motorway', 'trunk', 'primary')) + AND ST_Length(geometry) > 50 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen4_geometry_idx - ON osm_transportation_merge_linestring_gen4 USING gist(geometry); + ON osm_transportation_merge_linestring_gen4 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen4_highway_partial_idx - ON osm_transportation_merge_linestring_gen4(highway, construction) - WHERE highway IN ('motorway','trunk', 'primary', 'construction'); + ON osm_transportation_merge_linestring_gen4 (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'primary', 'construction'); -- etldoc: osm_transportation_merge_linestring_gen4 -> osm_transportation_merge_linestring_gen5 -CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen5 AS ( - SELECT ST_Simplify(geometry, 500) AS geometry, osm_id, highway, construction, z_order - FROM osm_transportation_merge_linestring_gen4 - WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) - AND ST_Length(geometry) > 100 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen5 AS +( +SELECT ST_Simplify(geometry, 500) AS geometry, osm_id, highway, construction, z_order +FROM osm_transportation_merge_linestring_gen4 +WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk')) + AND ST_Length(geometry) > 100 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen5_geometry_idx - ON osm_transportation_merge_linestring_gen5 USING gist(geometry); + ON osm_transportation_merge_linestring_gen5 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen5_highway_partial_idx - ON osm_transportation_merge_linestring_gen5(highway, construction) - WHERE highway IN ('motorway','trunk', 'construction'); + ON osm_transportation_merge_linestring_gen5 (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'construction'); -- etldoc: osm_transportation_merge_linestring_gen5 -> osm_transportation_merge_linestring_gen6 -CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen6 AS ( - SELECT ST_Simplify(geometry, 1000) AS geometry, osm_id, highway, construction, z_order - FROM osm_transportation_merge_linestring_gen5 - WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) AND ST_Length(geometry) > 500 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen6 AS +( +SELECT ST_Simplify(geometry, 1000) AS geometry, osm_id, highway, construction, z_order +FROM osm_transportation_merge_linestring_gen5 +WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk')) + AND ST_Length(geometry) > 500 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen6_geometry_idx - ON osm_transportation_merge_linestring_gen6 USING gist(geometry); + ON osm_transportation_merge_linestring_gen6 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen6_highway_partial_idx - ON osm_transportation_merge_linestring_gen6(highway, construction) - WHERE highway IN ('motorway','trunk', 'construction'); + ON osm_transportation_merge_linestring_gen6 (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'construction'); -- etldoc: osm_transportation_merge_linestring_gen6 -> osm_transportation_merge_linestring_gen7 -CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen7 AS ( - SELECT ST_Simplify(geometry, 2000) AS geometry, osm_id, highway, construction, z_order - FROM osm_transportation_merge_linestring_gen6 - WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') AND ST_Length(geometry) > 1000 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE MATERIALIZED VIEW osm_transportation_merge_linestring_gen7 AS +( +SELECT ST_Simplify(geometry, 2000) AS geometry, osm_id, highway, construction, z_order +FROM osm_transportation_merge_linestring_gen6 +WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') + AND ST_Length(geometry) > 1000 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; CREATE INDEX IF NOT EXISTS osm_transportation_merge_linestring_gen7_geometry_idx - ON osm_transportation_merge_linestring_gen7 USING gist(geometry); + ON osm_transportation_merge_linestring_gen7 USING gist (geometry); -- Handle updates CREATE SCHEMA IF NOT EXISTS transportation; -CREATE TABLE IF NOT EXISTS transportation.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION transportation.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS transportation.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION transportation.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO transportation.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO transportation.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION transportation.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE NOTICE 'Refresh transportation'; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen3; @@ -131,19 +147,21 @@ CREATE OR REPLACE FUNCTION transportation.refresh() RETURNS trigger AS REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen5; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen6; REFRESH MATERIALIZED VIEW osm_transportation_merge_linestring_gen7; + -- noinspection SqlWithoutWhere DELETE FROM transportation.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag_transportation - AFTER INSERT OR UPDATE OR DELETE ON osm_highway_linestring + AFTER INSERT OR UPDATE OR DELETE + ON osm_highway_linestring FOR EACH STATEMENT - EXECUTE PROCEDURE transportation.flag(); +EXECUTE PROCEDURE transportation.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON transportation.updates + AFTER INSERT + ON transportation.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE transportation.refresh(); +EXECUTE PROCEDURE transportation.refresh(); diff --git a/layers/transportation_name/layer.sql b/layers/transportation_name/layer.sql index ffc3a3d..1d148f4 100644 --- a/layers/transportation_name/layer.sql +++ b/layers/transportation_name/layer.sql @@ -1,131 +1,152 @@ - -- etldoc: layer_transportation_name[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_transportation_name | z6 | z7 | z8 | z9 | z10 | z11 | z12| z13| z14+" ] ; CREATE OR REPLACE FUNCTION layer_transportation_name(bbox geometry, zoom_level integer) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, - name_de text, tags hstore, ref text, ref_length int, network text, class - text, subclass text, layer INT, level INT, indoor INT) AS $$ - SELECT osm_id, geometry, - NULLIF(name, '') AS name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - tags, - NULLIF(ref, ''), NULLIF(LENGTH(ref), 0) AS ref_length, - --TODO: The road network of the road is not yet implemented - case - when network is not null - then network::text - when length(coalesce(ref, ''))>0 - then 'road' - end as network, - highway_class(highway, '', construction) AS class, - CASE - WHEN highway IS NOT NULL AND highway_class(highway, '', construction) = 'path' - THEN highway - END AS subclass, - NULLIF(layer, 0) AS layer, - "level", - CASE WHEN indoor=TRUE THEN 1 END as indoor - FROM ( - - -- etldoc: osm_transportation_name_linestring_gen4 -> layer_transportation_name:z6 - SELECT *, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor - FROM osm_transportation_name_linestring_gen4 - WHERE zoom_level = 6 - UNION ALL - - -- etldoc: osm_transportation_name_linestring_gen3 -> layer_transportation_name:z7 - SELECT *, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor - FROM osm_transportation_name_linestring_gen3 - WHERE zoom_level = 7 - UNION ALL - - -- etldoc: osm_transportation_name_linestring_gen2 -> layer_transportation_name:z8 - SELECT *, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor - FROM osm_transportation_name_linestring_gen2 - WHERE zoom_level = 8 - UNION ALL - - -- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z9 - -- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z10 - -- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z11 - SELECT *, - NULL::int AS layer, NULL::int AS level, NULL::boolean AS indoor - FROM osm_transportation_name_linestring_gen1 - WHERE zoom_level BETWEEN 9 AND 11 - UNION ALL - - -- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z12 - SELECT - geometry, - osm_id, - name, - name_en, - name_de, - "tags", - ref, - highway, - construction, - network, - z_order, - layer, - "level", - indoor - FROM osm_transportation_name_linestring - WHERE zoom_level = 12 - AND LineLabel(zoom_level, COALESCE(NULLIF(name, ''), ref), geometry) - AND highway_class(highway, '', construction) NOT IN ('minor', 'track', 'path') - AND NOT highway_is_link(highway) - UNION ALL - - -- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z13 - SELECT - geometry, - osm_id, - name, - name_en, - name_de, - "tags", - ref, - highway, - construction, - network, - z_order, - layer, - "level", - indoor - FROM osm_transportation_name_linestring - WHERE zoom_level = 13 - AND LineLabel(zoom_level, COALESCE(NULLIF(name, ''), ref), geometry) - AND highway_class(highway, '', construction) NOT IN ('track', 'path') - UNION ALL - - -- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z14_ - SELECT - geometry, - osm_id, - name, - name_en, - name_de, - "tags", - ref, - highway, - construction, - network, - z_order, - layer, - "level", - indoor - FROM osm_transportation_name_linestring - WHERE zoom_level >= 14 - - ) AS zoom_levels - WHERE geometry && bbox - ORDER BY z_order ASC; + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + tags hstore, + ref text, + ref_length int, + network text, + class text, + subclass text, + layer int, + level int, + indoor int + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT osm_id, + geometry, + NULLIF(name, '') AS name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + tags, + NULLIF(ref, ''), + NULLIF(LENGTH(ref), 0) AS ref_length, + --TODO: The road network of the road is not yet implemented + CASE + WHEN network IS NOT NULL + THEN network::text + WHEN length(coalesce(ref, '')) > 0 + THEN 'road' + END AS network, + highway_class(highway, '', construction) AS class, + CASE + WHEN highway IS NOT NULL AND highway_class(highway, '', construction) = 'path' + THEN highway + END AS subclass, + NULLIF(layer, 0) AS layer, + "level", + CASE WHEN indoor = TRUE THEN 1 END AS indoor +FROM ( + + -- etldoc: osm_transportation_name_linestring_gen4 -> layer_transportation_name:z6 + SELECT *, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor + FROM osm_transportation_name_linestring_gen4 + WHERE zoom_level = 6 + UNION ALL + + -- etldoc: osm_transportation_name_linestring_gen3 -> layer_transportation_name:z7 + SELECT *, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor + FROM osm_transportation_name_linestring_gen3 + WHERE zoom_level = 7 + UNION ALL + + -- etldoc: osm_transportation_name_linestring_gen2 -> layer_transportation_name:z8 + SELECT *, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor + FROM osm_transportation_name_linestring_gen2 + WHERE zoom_level = 8 + UNION ALL + + -- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z9 + -- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z10 + -- etldoc: osm_transportation_name_linestring_gen1 -> layer_transportation_name:z11 + SELECT *, + NULL::int AS layer, + NULL::int AS level, + NULL::boolean AS indoor + FROM osm_transportation_name_linestring_gen1 + WHERE zoom_level BETWEEN 9 AND 11 + UNION ALL + + -- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z12 + SELECT geometry, + osm_id, + name, + name_en, + name_de, + "tags", + ref, + highway, + construction, + network, + z_order, + layer, + "level", + indoor + FROM osm_transportation_name_linestring + WHERE zoom_level = 12 + AND LineLabel(zoom_level, COALESCE(NULLIF(name, ''), ref), geometry) + AND highway_class(highway, '', construction) NOT IN ('minor', 'track', 'path') + AND NOT highway_is_link(highway) + UNION ALL + + -- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z13 + SELECT geometry, + osm_id, + name, + name_en, + name_de, + "tags", + ref, + highway, + construction, + network, + z_order, + layer, + "level", + indoor + FROM osm_transportation_name_linestring + WHERE zoom_level = 13 + AND LineLabel(zoom_level, COALESCE(NULLIF(name, ''), ref), geometry) + AND highway_class(highway, '', construction) NOT IN ('track', 'path') + UNION ALL + + -- etldoc: osm_transportation_name_linestring -> layer_transportation_name:z14_ + SELECT geometry, + osm_id, + name, + name_en, + name_de, + "tags", + ref, + highway, + construction, + network, + z_order, + layer, + "level", + indoor + FROM osm_transportation_name_linestring + WHERE zoom_level >= 14 + ) AS zoom_levels +WHERE geometry && bbox +ORDER BY z_order ASC; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/transportation_name/network_type.sql b/layers/transportation_name/network_type.sql index 3250991..e207cb3 100644 --- a/layers/transportation_name/network_type.sql +++ b/layers/transportation_name/network_type.sql @@ -5,26 +5,27 @@ DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen2 CASCADE DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen3 CASCADE; DROP MATERIALIZED VIEW IF EXISTS osm_transportation_name_linestring_gen4 CASCADE; -DO $$ -BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'route_network_type') THEN - CREATE TYPE route_network_type AS ENUM ( - 'us-interstate', 'us-highway', 'us-state', - 'ca-transcanada', - 'gb-motorway', 'gb-trunk' - ); - END IF; -END +DO $$ -; + BEGIN + IF NOT EXISTS(SELECT 1 FROM pg_type WHERE typname = 'route_network_type') THEN + CREATE TYPE route_network_type AS enum ( + 'us-interstate', 'us-highway', 'us-state', + 'ca-transcanada', + 'gb-motorway', 'gb-trunk' + ); + END IF; + END +$$; -DO $$ +DO +$$ BEGIN BEGIN - ALTER TABLE osm_route_member ADD COLUMN network_type route_network_type; + ALTER TABLE osm_route_member + ADD COLUMN network_type route_network_type; EXCEPTION WHEN duplicate_column THEN RAISE NOTICE 'column network_type already exists in network_type.'; END; END; -$$ -; +$$; diff --git a/layers/transportation_name/update_route_member.sql b/layers/transportation_name/update_route_member.sql index 19a9f16..178d94d 100644 --- a/layers/transportation_name/update_route_member.sql +++ b/layers/transportation_name/update_route_member.sql @@ -2,67 +2,69 @@ DROP TRIGGER IF EXISTS trigger_flag_transportation_name ON osm_route_member; -- create GBR relations (so we can use it in the same way as other relations) -CREATE OR REPLACE FUNCTION update_gbr_route_members() RETURNS VOID AS $$ -DECLARE gbr_geom geometry; +CREATE OR REPLACE FUNCTION update_gbr_route_members() RETURNS void AS +$$ +DECLARE + gbr_geom geometry; BEGIN - SELECT st_buffer(geometry, 10000) INTO gbr_geom FROM ne_10m_admin_0_countries where iso_a2 = 'GB'; + SELECT st_buffer(geometry, 10000) INTO gbr_geom FROM ne_10m_admin_0_countries WHERE iso_a2 = 'GB'; DELETE FROM osm_route_member WHERE network IN ('omt-gb-motorway', 'omt-gb-trunk'); INSERT INTO osm_route_member (osm_id, member, ref, network) - SELECT 0, osm_id, substring(ref FROM E'^[AM][0-9AM()]+'), - CASE WHEN highway = 'motorway' THEN 'omt-gb-motorway' ELSE 'omt-gb-trunk' END + SELECT 0, + osm_id, + substring(ref FROM E'^[AM][0-9AM()]+'), + CASE WHEN highway = 'motorway' THEN 'omt-gb-motorway' ELSE 'omt-gb-trunk' END FROM osm_highway_linestring - WHERE - length(ref)>0 AND - ST_Intersects(geometry, gbr_geom) AND - highway IN ('motorway', 'trunk') - ; + WHERE length(ref) > 0 + AND ST_Intersects(geometry, gbr_geom) + AND highway IN ('motorway', 'trunk'); END; $$ LANGUAGE plpgsql; -- etldoc: osm_route_member -> osm_route_member -CREATE OR REPLACE FUNCTION update_osm_route_member() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_route_member() RETURNS void AS +$$ BEGIN - PERFORM update_gbr_route_members(); + PERFORM update_gbr_route_members(); - -- see http://wiki.openstreetmap.org/wiki/Relation:route#Road_routes - UPDATE osm_route_member - SET network_type = - CASE - WHEN network = 'US:I' THEN 'us-interstate'::route_network_type - WHEN network = 'US:US' THEN 'us-highway'::route_network_type - WHEN network LIKE 'US:__' THEN 'us-state'::route_network_type - -- https://en.wikipedia.org/wiki/Trans-Canada_Highway - -- TODO: improve hierarchical queries using - -- http://www.openstreetmap.org/relation/1307243 - -- however the relation does not cover the whole Trans-Canada_Highway - WHEN - (network = 'CA:transcanada') OR - (network = 'CA:BC:primary' AND ref IN ('16')) OR - (name = 'Yellowhead Highway (AB)' AND ref IN ('16')) OR - (network = 'CA:SK:primary' AND ref IN ('16')) OR - (network = 'CA:ON:primary' AND ref IN ('17', '417')) OR - (name = 'Route Transcanadienne') OR - (network = 'CA:NB:primary' AND ref IN ('2', '16')) OR - (network = 'CA:PE' AND ref IN ('1')) OR - (network = 'CA:NS' AND ref IN ('104', '105')) OR - (network = 'CA:NL:R' AND ref IN ('1')) OR - (name = 'Trans-Canada Highway') - THEN 'ca-transcanada'::route_network_type - WHEN network = 'omt-gb-motorway' THEN 'gb-motorway'::route_network_type - WHEN network = 'omt-gb-trunk' THEN 'gb-trunk'::route_network_type - END - ; + -- see http://wiki.openstreetmap.org/wiki/Relation:route#Road_routes + UPDATE osm_route_member + SET network_type = + CASE + WHEN network = 'US:I' THEN 'us-interstate'::route_network_type + WHEN network = 'US:US' THEN 'us-highway'::route_network_type + WHEN network LIKE 'US:__' THEN 'us-state'::route_network_type + -- https://en.wikipedia.org/wiki/Trans-Canada_Highway + -- TODO: improve hierarchical queries using + -- http://www.openstreetmap.org/relation/1307243 + -- however the relation does not cover the whole Trans-Canada_Highway + WHEN + (network = 'CA:transcanada') OR + (network = 'CA:BC:primary' AND ref IN ('16')) OR + (name = 'Yellowhead Highway (AB)' AND ref IN ('16')) OR + (network = 'CA:SK:primary' AND ref IN ('16')) OR + (network = 'CA:ON:primary' AND ref IN ('17', '417')) OR + (name = 'Route Transcanadienne') OR + (network = 'CA:NB:primary' AND ref IN ('2', '16')) OR + (network = 'CA:PE' AND ref IN ('1')) OR + (network = 'CA:NS' AND ref IN ('104', '105')) OR + (network = 'CA:NL:R' AND ref IN ('1')) OR + (name = 'Trans-Canada Highway') + THEN 'ca-transcanada'::route_network_type + WHEN network = 'omt-gb-motorway' THEN 'gb-motorway'::route_network_type + WHEN network = 'omt-gb-trunk' THEN 'gb-trunk'::route_network_type + END; END; $$ LANGUAGE plpgsql; -CREATE INDEX IF NOT EXISTS osm_route_member_network_idx ON osm_route_member("network"); -CREATE INDEX IF NOT EXISTS osm_route_member_member_idx ON osm_route_member("member"); -CREATE INDEX IF NOT EXISTS osm_route_member_name_idx ON osm_route_member("name"); -CREATE INDEX IF NOT EXISTS osm_route_member_ref_idx ON osm_route_member("ref"); +CREATE INDEX IF NOT EXISTS osm_route_member_network_idx ON osm_route_member ("network"); +CREATE INDEX IF NOT EXISTS osm_route_member_member_idx ON osm_route_member ("member"); +CREATE INDEX IF NOT EXISTS osm_route_member_name_idx ON osm_route_member ("name"); +CREATE INDEX IF NOT EXISTS osm_route_member_ref_idx ON osm_route_member ("ref"); SELECT update_osm_route_member(); -CREATE INDEX IF NOT EXISTS osm_route_member_network_type_idx ON osm_route_member("network_type"); +CREATE INDEX IF NOT EXISTS osm_route_member_network_type_idx ON osm_route_member ("network_type"); diff --git a/layers/transportation_name/update_transportation_name.sql b/layers/transportation_name/update_transportation_name.sql index 236e9ac..ae4503a 100644 --- a/layers/transportation_name/update_transportation_name.sql +++ b/layers/transportation_name/update_transportation_name.sql @@ -9,139 +9,194 @@ DROP TRIGGER IF EXISTS trigger_refresh ON transportation_name.updates; -- etldoc: osm_highway_linestring -> osm_transportation_name_network -- etldoc: osm_route_member -> osm_transportation_name_network -CREATE MATERIALIZED VIEW osm_transportation_name_network AS ( - SELECT - hl.geometry, - hl.osm_id, - CASE WHEN length(hl.name)>15 THEN osml10n_street_abbrev_all(hl.name) ELSE hl.name END AS "name", - CASE WHEN length(hl.name_en)>15 THEN osml10n_street_abbrev_en(hl.name_en) ELSE hl.name_en END AS "name_en", - CASE WHEN length(hl.name_de)>15 THEN osml10n_street_abbrev_de(hl.name_de) ELSE hl.name_de END AS "name_de", - hl.tags, - rm.network_type, - CASE - WHEN (rm.network_type is not null AND nullif(rm.ref::text, '') is not null) - then rm.ref::text - else hl.ref - end as ref, - hl.highway, - hl.construction, - CASE WHEN highway IN ('footway', 'steps') THEN layer END AS layer, - CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level", - CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor, - ROW_NUMBER() OVER(PARTITION BY hl.osm_id - ORDER BY rm.network_type) AS "rank", - hl.z_order - FROM osm_highway_linestring hl - left join osm_route_member rm on (rm.member = hl.osm_id) -) /* DELAY_MATERIALIZED_VIEW_CREATION */; -CREATE INDEX IF NOT EXISTS osm_transportation_name_network_geometry_idx ON osm_transportation_name_network USING gist(geometry); +CREATE MATERIALIZED VIEW osm_transportation_name_network AS +( +SELECT hl.geometry, + hl.osm_id, + CASE WHEN length(hl.name) > 15 THEN osml10n_street_abbrev_all(hl.name) ELSE hl.name END AS "name", + CASE WHEN length(hl.name_en) > 15 THEN osml10n_street_abbrev_en(hl.name_en) ELSE hl.name_en END AS "name_en", + CASE WHEN length(hl.name_de) > 15 THEN osml10n_street_abbrev_de(hl.name_de) ELSE hl.name_de END AS "name_de", + hl.tags, + rm.network_type, + CASE + WHEN (rm.network_type IS NOT NULL AND nullif(rm.ref::text, '') IS NOT NULL) + THEN rm.ref::text + ELSE hl.ref + END AS ref, + hl.highway, + hl.construction, + CASE WHEN highway IN ('footway', 'steps') THEN layer END AS layer, + CASE WHEN highway IN ('footway', 'steps') THEN "level" END AS "level", + CASE WHEN highway IN ('footway', 'steps') THEN indoor END AS indoor, + ROW_NUMBER() OVER (PARTITION BY hl.osm_id + ORDER BY rm.network_type) AS "rank", + hl.z_order +FROM osm_highway_linestring hl + LEFT JOIN osm_route_member rm ON (rm.member = hl.osm_id) + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE INDEX IF NOT EXISTS osm_transportation_name_network_geometry_idx ON osm_transportation_name_network USING gist (geometry); -- etldoc: osm_transportation_name_network -> osm_transportation_name_linestring -CREATE MATERIALIZED VIEW osm_transportation_name_linestring AS ( - SELECT - (ST_Dump(geometry)).geom AS geometry, - NULL::bigint AS osm_id, - name, - name_en, - name_de, - tags || get_basic_names(tags, geometry) AS "tags", - ref, - highway, - construction, - "level", - layer, - indoor, - network_type AS network, - z_order - FROM ( - SELECT - ST_LineMerge(ST_Collect(geometry)) AS geometry, - name, - name_en, - name_de, - hstore(string_agg(nullif(slice_language_tags(tags || hstore(ARRAY['name', name, 'name:en', name_en, 'name:de', name_de]))::text, ''), ',')) - AS "tags", - ref, - highway, - construction, - "level", - layer, - indoor, - network_type, - min(z_order) AS z_order - FROM osm_transportation_name_network - WHERE ("rank"=1 OR "rank" is null) - AND (name <> '' OR ref <> '') - AND NULLIF(highway, '') IS NOT NULL - group by name, name_en, name_de, ref, highway, construction, "level", layer, indoor, network_type - ) AS highway_union -) /* DELAY_MATERIALIZED_VIEW_CREATION */; -CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_geometry_idx ON osm_transportation_name_linestring USING gist(geometry); +CREATE MATERIALIZED VIEW osm_transportation_name_linestring AS +( +SELECT (ST_Dump(geometry)).geom AS geometry, + NULL::bigint AS osm_id, + name, + name_en, + name_de, + tags || get_basic_names(tags, geometry) AS "tags", + ref, + highway, + construction, + "level", + layer, + indoor, + network_type AS network, + z_order +FROM ( + SELECT ST_LineMerge(ST_Collect(geometry)) AS geometry, + name, + name_en, + name_de, + hstore(string_agg(nullif(slice_language_tags(tags || + hstore(ARRAY ['name', name, 'name:en', name_en, 'name:de', name_de]))::text, + ''), ',')) + AS "tags", + ref, + highway, + construction, + "level", + layer, + indoor, + network_type, + min(z_order) AS z_order + FROM osm_transportation_name_network + WHERE ("rank" = 1 OR "rank" IS NULL) + AND (name <> '' OR ref <> '') + AND NULLIF(highway, '') IS NOT NULL + GROUP BY name, name_en, name_de, ref, highway, construction, "level", layer, indoor, network_type + ) AS highway_union + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_geometry_idx ON osm_transportation_name_linestring USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_highway_partial_idx - ON osm_transportation_name_linestring(highway, construction) - WHERE highway IN ('motorway','trunk', 'construction'); + ON osm_transportation_name_linestring (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'construction'); -- etldoc: osm_transportation_name_linestring -> osm_transportation_name_linestring_gen1 -CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen1 AS ( - SELECT ST_Simplify(geometry, 50) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order - FROM osm_transportation_name_linestring - WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) AND ST_Length(geometry) > 8000 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; -CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_geometry_idx ON osm_transportation_name_linestring_gen1 USING gist(geometry); +CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen1 AS +( +SELECT ST_Simplify(geometry, 50) AS geometry, + osm_id, + name, + name_en, + name_de, + tags, + ref, + highway, + construction, + network, + z_order +FROM osm_transportation_name_linestring +WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk')) + AND ST_Length(geometry) > 8000 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_geometry_idx ON osm_transportation_name_linestring_gen1 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen1_highway_partial_idx - ON osm_transportation_name_linestring_gen1(highway, construction) - WHERE highway IN ('motorway','trunk', 'construction'); + ON osm_transportation_name_linestring_gen1 (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'construction'); -- etldoc: osm_transportation_name_linestring_gen1 -> osm_transportation_name_linestring_gen2 -CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen2 AS ( - SELECT ST_Simplify(geometry, 120) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order - FROM osm_transportation_name_linestring_gen1 - WHERE (highway IN ('motorway','trunk') OR highway = 'construction' AND construction IN ('motorway','trunk')) AND ST_Length(geometry) > 14000 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; -CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_geometry_idx ON osm_transportation_name_linestring_gen2 USING gist(geometry); +CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen2 AS +( +SELECT ST_Simplify(geometry, 120) AS geometry, + osm_id, + name, + name_en, + name_de, + tags, + ref, + highway, + construction, + network, + z_order +FROM osm_transportation_name_linestring_gen1 +WHERE (highway IN ('motorway', 'trunk') OR highway = 'construction' AND construction IN ('motorway', 'trunk')) + AND ST_Length(geometry) > 14000 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_geometry_idx ON osm_transportation_name_linestring_gen2 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen2_highway_partial_idx - ON osm_transportation_name_linestring_gen2(highway, construction) - WHERE highway IN ('motorway','trunk', 'construction'); + ON osm_transportation_name_linestring_gen2 (highway, construction) + WHERE highway IN ('motorway', 'trunk', 'construction'); -- etldoc: osm_transportation_name_linestring_gen2 -> osm_transportation_name_linestring_gen3 -CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen3 AS ( - SELECT ST_Simplify(geometry, 200) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order - FROM osm_transportation_name_linestring_gen2 - WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') AND ST_Length(geometry) > 20000 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; -CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_geometry_idx ON osm_transportation_name_linestring_gen3 USING gist(geometry); +CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen3 AS +( +SELECT ST_Simplify(geometry, 200) AS geometry, + osm_id, + name, + name_en, + name_de, + tags, + ref, + highway, + construction, + network, + z_order +FROM osm_transportation_name_linestring_gen2 +WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') + AND ST_Length(geometry) > 20000 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_geometry_idx ON osm_transportation_name_linestring_gen3 USING gist (geometry); CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen3_highway_partial_idx - ON osm_transportation_name_linestring_gen3(highway, construction) - WHERE highway IN ('motorway', 'construction'); + ON osm_transportation_name_linestring_gen3 (highway, construction) + WHERE highway IN ('motorway', 'construction'); -- etldoc: osm_transportation_name_linestring_gen3 -> osm_transportation_name_linestring_gen4 -CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen4 AS ( - SELECT ST_Simplify(geometry, 500) AS geometry, osm_id, name, name_en, name_de, tags, ref, highway, construction, network, z_order - FROM osm_transportation_name_linestring_gen3 - WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') AND ST_Length(geometry) > 20000 -) /* DELAY_MATERIALIZED_VIEW_CREATION */; -CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen4_geometry_idx ON osm_transportation_name_linestring_gen4 USING gist(geometry); +CREATE MATERIALIZED VIEW osm_transportation_name_linestring_gen4 AS +( +SELECT ST_Simplify(geometry, 500) AS geometry, + osm_id, + name, + name_en, + name_de, + tags, + ref, + highway, + construction, + network, + z_order +FROM osm_transportation_name_linestring_gen3 +WHERE (highway = 'motorway' OR highway = 'construction' AND construction = 'motorway') + AND ST_Length(geometry) > 20000 + ) /* DELAY_MATERIALIZED_VIEW_CREATION */; +CREATE INDEX IF NOT EXISTS osm_transportation_name_linestring_gen4_geometry_idx ON osm_transportation_name_linestring_gen4 USING gist (geometry); -- Handle updates CREATE SCHEMA IF NOT EXISTS transportation_name; -CREATE TABLE IF NOT EXISTS transportation_name.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION transportation_name.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS transportation_name.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION transportation_name.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO transportation_name.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO transportation_name.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION transportation_name.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh transportation_name'; PERFORM update_osm_route_member(); REFRESH MATERIALIZED VIEW osm_transportation_name_network; @@ -150,24 +205,27 @@ CREATE OR REPLACE FUNCTION transportation_name.refresh() RETURNS trigger AS REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen2; REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen3; REFRESH MATERIALIZED VIEW osm_transportation_name_linestring_gen4; + -- noinspection SqlWithoutWhere DELETE FROM transportation_name.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag_transportation_name - AFTER INSERT OR UPDATE OR DELETE ON osm_route_member + AFTER INSERT OR UPDATE OR DELETE + ON osm_route_member FOR EACH STATEMENT - EXECUTE PROCEDURE transportation_name.flag(); +EXECUTE PROCEDURE transportation_name.flag(); CREATE TRIGGER trigger_flag_transportation_name - AFTER INSERT OR UPDATE OR DELETE ON osm_highway_linestring + AFTER INSERT OR UPDATE OR DELETE + ON osm_highway_linestring FOR EACH STATEMENT - EXECUTE PROCEDURE transportation_name.flag(); +EXECUTE PROCEDURE transportation_name.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON transportation_name.updates + AFTER INSERT + ON transportation_name.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE transportation_name.refresh(); +EXECUTE PROCEDURE transportation_name.refresh(); diff --git a/layers/water/update_water.sql b/layers/water/update_water.sql new file mode 100644 index 0000000..9094fc5 --- /dev/null +++ b/layers/water/update_water.sql @@ -0,0 +1,78 @@ +-- This statement can be deleted after the water importer image stops creating this object as a table +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_ocean_polygon_gen1 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + +-- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen1 +DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen1 CASCADE; +CREATE MATERIALIZED VIEW osm_ocean_polygon_gen1 AS +( +SELECT ST_Simplify(geometry, 20) AS geometry +FROM osm_ocean_polygon + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen1_idx ON osm_ocean_polygon_gen1 USING gist (geometry); + + +-- This statement can be deleted after the water importer image stops creating this object as a table +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_ocean_polygon_gen2 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + +-- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen2 +DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen2 CASCADE; +CREATE MATERIALIZED VIEW osm_ocean_polygon_gen2 AS +( +SELECT ST_Simplify(geometry, 40) AS geometry +FROM osm_ocean_polygon + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen2_idx ON osm_ocean_polygon_gen2 USING gist (geometry); + + +-- This statement can be deleted after the water importer image stops creating this object as a table +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_ocean_polygon_gen3 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + +-- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen3 +DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen3 CASCADE; +CREATE MATERIALIZED VIEW osm_ocean_polygon_gen3 AS +( +SELECT ST_Simplify(geometry, 80) AS geometry +FROM osm_ocean_polygon + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen3_idx ON osm_ocean_polygon_gen3 USING gist (geometry); + + +-- This statement can be deleted after the water importer image stops creating this object as a table +DO +$$ + BEGIN + DROP TABLE IF EXISTS osm_ocean_polygon_gen4 CASCADE; + EXCEPTION + WHEN wrong_object_type THEN + END; +$$ LANGUAGE plpgsql; + +-- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen4 +DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen4 CASCADE; +CREATE MATERIALIZED VIEW osm_ocean_polygon_gen4 AS +( +SELECT ST_Simplify(geometry, 160) AS geometry +FROM osm_ocean_polygon + ) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; +CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen4_idx ON osm_ocean_polygon_gen4 USING gist (geometry); diff --git a/layers/water/water.sql b/layers/water/water.sql index a478428..f218dd9 100644 --- a/layers/water/water.sql +++ b/layers/water/water.sql @@ -1,384 +1,390 @@ --- This statement can be deleted after the water importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_ocean_polygon_gen1 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; --- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen1 -DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen1 CASCADE; -CREATE MATERIALIZED VIEW osm_ocean_polygon_gen1 AS ( - SELECT ST_Simplify(geometry, 20) AS geometry - FROM osm_ocean_polygon -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; -CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen1_idx ON osm_ocean_polygon_gen1 USING gist (geometry); - - --- This statement can be deleted after the water importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_ocean_polygon_gen2 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; --- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen2 -DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen2 CASCADE; -CREATE MATERIALIZED VIEW osm_ocean_polygon_gen2 AS ( - SELECT ST_Simplify(geometry, 40) AS geometry - FROM osm_ocean_polygon -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; -CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen2_idx ON osm_ocean_polygon_gen2 USING gist (geometry); - - --- This statement can be deleted after the water importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_ocean_polygon_gen3 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; --- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen3 -DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen3 CASCADE; -CREATE MATERIALIZED VIEW osm_ocean_polygon_gen3 AS ( - SELECT ST_Simplify(geometry, 80) AS geometry - FROM osm_ocean_polygon -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; -CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen3_idx ON osm_ocean_polygon_gen3 USING gist (geometry); - - --- This statement can be deleted after the water importer image stops creating this object as a table -DO $$ BEGIN DROP TABLE IF EXISTS osm_ocean_polygon_gen4 CASCADE; EXCEPTION WHEN wrong_object_type THEN END; $$ language 'plpgsql'; --- etldoc: osm_ocean_polygon -> osm_ocean_polygon_gen4 -DROP MATERIALIZED VIEW IF EXISTS osm_ocean_polygon_gen4 CASCADE; -CREATE MATERIALIZED VIEW osm_ocean_polygon_gen4 AS ( - SELECT ST_Simplify(geometry, 160) AS geometry - FROM osm_ocean_polygon -) /* DELAY_MATERIALIZED_VIEW_CREATION */ ; -CREATE INDEX IF NOT EXISTS osm_ocean_polygon_gen4_idx ON osm_ocean_polygon_gen4 USING gist (geometry); - - - -CREATE OR REPLACE FUNCTION water_class(waterway TEXT) RETURNS TEXT AS $$ - SELECT CASE +CREATE OR REPLACE FUNCTION water_class(waterway text) RETURNS text AS +$$ +SELECT CASE %%FIELD_MAPPING: class %% ELSE 'river' - END; + END; +$$ LANGUAGE SQL IMMUTABLE + PARALLEL SAFE; + + +CREATE OR REPLACE FUNCTION waterway_brunnel(is_bridge bool, is_tunnel bool) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; - - -CREATE OR REPLACE FUNCTION waterway_brunnel(is_bridge BOOL, is_tunnel BOOL) RETURNS TEXT AS $$ - SELECT CASE - WHEN is_bridge THEN 'bridge' - WHEN is_tunnel THEN 'tunnel' - END; -$$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN is_bridge THEN 'bridge' + WHEN is_tunnel THEN 'tunnel' + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; -CREATE OR REPLACE VIEW water_z0 AS ( - -- etldoc: ne_110m_ocean -> water_z0 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_110m_ocean - UNION ALL - -- etldoc: ne_110m_lakes -> water_z0 - SELECT geometry, - 'lake'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_110m_lakes -); +CREATE OR REPLACE VIEW water_z0 AS +( +-- etldoc: ne_110m_ocean -> water_z0 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_110m_ocean +UNION ALL +-- etldoc: ne_110m_lakes -> water_z0 +SELECT geometry, + 'lake'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_110m_lakes + ); -CREATE OR REPLACE VIEW water_z1 AS ( - -- etldoc: ne_110m_ocean -> water_z1 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_110m_ocean - UNION ALL - -- etldoc: ne_110m_lakes -> water_z1 - SELECT geometry, - 'lake'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_110m_lakes -); +CREATE OR REPLACE VIEW water_z1 AS +( +-- etldoc: ne_110m_ocean -> water_z1 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_110m_ocean +UNION ALL +-- etldoc: ne_110m_lakes -> water_z1 +SELECT geometry, + 'lake'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_110m_lakes + ); -CREATE OR REPLACE VIEW water_z2 AS ( - -- etldoc: ne_50m_ocean -> water_z2 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_50m_ocean - UNION ALL - -- etldoc: ne_50m_lakes -> water_z2 - SELECT geometry, - 'lake'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_50m_lakes -); +CREATE OR REPLACE VIEW water_z2 AS +( +-- etldoc: ne_50m_ocean -> water_z2 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_50m_ocean +UNION ALL +-- etldoc: ne_50m_lakes -> water_z2 +SELECT geometry, + 'lake'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_50m_lakes + ); -CREATE OR REPLACE VIEW water_z4 AS ( - -- etldoc: ne_50m_ocean -> water_z4 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_50m_ocean - UNION ALL - -- etldoc: ne_10m_lakes -> water_z4 - SELECT geometry, - 'lake'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_10m_lakes -); +CREATE OR REPLACE VIEW water_z4 AS +( +-- etldoc: ne_50m_ocean -> water_z4 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_50m_ocean +UNION ALL +-- etldoc: ne_10m_lakes -> water_z4 +SELECT geometry, + 'lake'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_10m_lakes + ); -CREATE OR REPLACE VIEW water_z5 AS ( - -- etldoc: ne_10m_ocean -> water_z5 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_10m_ocean - UNION ALL - -- etldoc: ne_10m_lakes -> water_z5 - SELECT geometry, - 'lake'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM ne_10m_lakes -); +CREATE OR REPLACE VIEW water_z5 AS +( +-- etldoc: ne_10m_ocean -> water_z5 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_10m_ocean +UNION ALL +-- etldoc: ne_10m_lakes -> water_z5 +SELECT geometry, + 'lake'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM ne_10m_lakes + ); -CREATE OR REPLACE VIEW water_z6 AS ( - -- etldoc: osm_ocean_polygon_gen4 -> water_z6 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon_gen4 - UNION ALL - -- etldoc: osm_water_polygon_gen6 -> water_z6 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_water_polygon_gen6 - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z6 AS +( +-- etldoc: osm_ocean_polygon_gen4 -> water_z6 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon_gen4 +UNION ALL +-- etldoc: osm_water_polygon_gen6 -> water_z6 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_water_polygon_gen6 +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z7 AS ( - -- etldoc: osm_ocean_polygon_gen4 -> water_z7 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon_gen4 - UNION ALL - -- etldoc: osm_water_polygon_gen5 -> water_z7 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_water_polygon_gen5 - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z7 AS +( +-- etldoc: osm_ocean_polygon_gen4 -> water_z7 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon_gen4 +UNION ALL +-- etldoc: osm_water_polygon_gen5 -> water_z7 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_water_polygon_gen5 +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z8 AS ( - -- etldoc: osm_ocean_polygon_gen4 -> water_z8 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon_gen4 - UNION ALL - -- etldoc: osm_water_polygon_gen4 -> water_z8 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_water_polygon_gen4 - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z8 AS +( +-- etldoc: osm_ocean_polygon_gen4 -> water_z8 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon_gen4 +UNION ALL +-- etldoc: osm_water_polygon_gen4 -> water_z8 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_water_polygon_gen4 +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z9 AS ( - -- etldoc: osm_ocean_polygon_gen3 -> water_z9 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon_gen3 - UNION ALL - -- etldoc: osm_water_polygon_gen3 -> water_z9 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_water_polygon_gen3 - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z9 AS +( +-- etldoc: osm_ocean_polygon_gen3 -> water_z9 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon_gen3 +UNION ALL +-- etldoc: osm_water_polygon_gen3 -> water_z9 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_water_polygon_gen3 +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z10 AS ( - -- etldoc: osm_ocean_polygon_gen2 -> water_z10 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon_gen2 - UNION ALL - -- etldoc: osm_water_polygon_gen2 -> water_z10 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_water_polygon_gen2 - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z10 AS +( +-- etldoc: osm_ocean_polygon_gen2 -> water_z10 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon_gen2 +UNION ALL +-- etldoc: osm_water_polygon_gen2 -> water_z10 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_water_polygon_gen2 +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z11 AS ( - -- etldoc: osm_ocean_polygon_gen1 -> water_z11 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon_gen1 - UNION ALL - -- etldoc: osm_water_polygon_gen1 -> water_z11 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_water_polygon_gen1 - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z11 AS +( +-- etldoc: osm_ocean_polygon_gen1 -> water_z11 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon_gen1 +UNION ALL +-- etldoc: osm_water_polygon_gen1 -> water_z11 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_water_polygon_gen1 +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z12 AS ( - -- etldoc: osm_ocean_polygon_gen1 -> water_z12 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon - UNION ALL - -- etldoc: osm_water_polygon -> water_z12 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - is_bridge, - is_tunnel - FROM osm_water_polygon - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z12 AS +( +-- etldoc: osm_ocean_polygon_gen1 -> water_z12 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon +UNION ALL +-- etldoc: osm_water_polygon -> water_z12 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + is_bridge, + is_tunnel +FROM osm_water_polygon +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z13 AS ( - -- etldoc: osm_ocean_polygon -> water_z13 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon - UNION ALL - -- etldoc: osm_water_polygon -> water_z13 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - is_bridge, - is_tunnel - FROM osm_water_polygon - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z13 AS +( +-- etldoc: osm_ocean_polygon -> water_z13 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon +UNION ALL +-- etldoc: osm_water_polygon -> water_z13 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + is_bridge, + is_tunnel +FROM osm_water_polygon +WHERE "natural" != 'bay' + ); -CREATE OR REPLACE VIEW water_z14 AS ( - -- etldoc: osm_ocean_polygon -> water_z14 - SELECT geometry, - 'ocean'::text AS class, - NULL::boolean AS is_intermittent, - NULL::boolean AS is_bridge, - NULL::boolean AS is_tunnel - FROM osm_ocean_polygon - UNION ALL - -- etldoc: osm_water_polygon -> water_z14 - SELECT geometry, - water_class(waterway) AS class, - is_intermittent, - is_bridge, - is_tunnel - FROM osm_water_polygon - WHERE "natural" != 'bay' -); +CREATE OR REPLACE VIEW water_z14 AS +( +-- etldoc: osm_ocean_polygon -> water_z14 +SELECT geometry, + 'ocean'::text AS class, + NULL::boolean AS is_intermittent, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel +FROM osm_ocean_polygon +UNION ALL +-- etldoc: osm_water_polygon -> water_z14 +SELECT geometry, + water_class(waterway) AS class, + is_intermittent, + is_bridge, + is_tunnel +FROM osm_water_polygon +WHERE "natural" != 'bay' + ); -- etldoc: layer_water [shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_water | z0|z1|z2|z3 | z4|z5|z6|z7| z8 | z9 | z10 | z11 | z12| z13| z14+" ] ; -CREATE OR REPLACE FUNCTION layer_water (bbox geometry, zoom_level int) -RETURNS TABLE(geometry geometry, class text, brunnel text, intermittent int) AS $$ - SELECT geometry, - class::text, - waterway_brunnel(is_bridge, is_tunnel) AS brunnel, - is_intermittent::int AS intermittent - FROM ( - -- etldoc: water_z0 -> layer_water:z0 - SELECT * FROM water_z0 WHERE zoom_level = 0 - UNION ALL - -- etldoc: water_z1 -> layer_water:z1 - SELECT * FROM water_z1 WHERE zoom_level = 1 - UNION ALL - -- etldoc: water_z2 -> layer_water:z2 - -- etldoc: water_z2 -> layer_water:z3 - SELECT * FROM water_z2 WHERE zoom_level BETWEEN 2 AND 3 - UNION ALL - -- etldoc: water_z4 -> layer_water:z4 - SELECT * FROM water_z4 WHERE zoom_level = 4 - UNION ALL - -- etldoc: water_z5 -> layer_water:z5 - SELECT * FROM water_z5 WHERE zoom_level = 5 - UNION ALL - -- etldoc: water_z6 -> layer_water:z6 - SELECT * FROM water_z6 WHERE zoom_level = 6 - UNION ALL - -- etldoc: water_z7 -> layer_water:z7 - SELECT * FROM water_z7 WHERE zoom_level = 7 - UNION ALL - -- etldoc: water_z8 -> layer_water:z8 - SELECT * FROM water_z8 WHERE zoom_level = 8 - UNION ALL - -- etldoc: water_z9 -> layer_water:z9 - SELECT * FROM water_z9 WHERE zoom_level = 9 - UNION ALL - -- etldoc: water_z10 -> layer_water:z10 - SELECT * FROM water_z10 WHERE zoom_level = 10 - UNION ALL - -- etldoc: water_z11 -> layer_water:z11 - SELECT * FROM water_z11 WHERE zoom_level = 11 - UNION ALL - -- etldoc: water_z12 -> layer_water:z12 - SELECT * FROM water_z12 WHERE zoom_level = 12 - UNION ALL - -- etldoc: water_z13 -> layer_water:z13 - SELECT * FROM water_z13 WHERE zoom_level = 13 - UNION ALL - -- etldoc: water_z14 -> layer_water:z14_ - SELECT * FROM water_z14 WHERE zoom_level >= 14 - ) AS zoom_levels - WHERE geometry && bbox; +CREATE OR REPLACE FUNCTION layer_water(bbox geometry, zoom_level int) + RETURNS TABLE + ( + geometry geometry, + class text, + brunnel text, + intermittent int + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT geometry, + class::text, + waterway_brunnel(is_bridge, is_tunnel) AS brunnel, + is_intermittent::int AS intermittent +FROM ( + -- etldoc: water_z0 -> layer_water:z0 + SELECT * + FROM water_z0 + WHERE zoom_level = 0 + UNION ALL + -- etldoc: water_z1 -> layer_water:z1 + SELECT * + FROM water_z1 + WHERE zoom_level = 1 + UNION ALL + -- etldoc: water_z2 -> layer_water:z2 + -- etldoc: water_z2 -> layer_water:z3 + SELECT * + FROM water_z2 + WHERE zoom_level BETWEEN 2 AND 3 + UNION ALL + -- etldoc: water_z4 -> layer_water:z4 + SELECT * + FROM water_z4 + WHERE zoom_level = 4 + UNION ALL + -- etldoc: water_z5 -> layer_water:z5 + SELECT * + FROM water_z5 + WHERE zoom_level = 5 + UNION ALL + -- etldoc: water_z6 -> layer_water:z6 + SELECT * + FROM water_z6 + WHERE zoom_level = 6 + UNION ALL + -- etldoc: water_z7 -> layer_water:z7 + SELECT * + FROM water_z7 + WHERE zoom_level = 7 + UNION ALL + -- etldoc: water_z8 -> layer_water:z8 + SELECT * + FROM water_z8 + WHERE zoom_level = 8 + UNION ALL + -- etldoc: water_z9 -> layer_water:z9 + SELECT * + FROM water_z9 + WHERE zoom_level = 9 + UNION ALL + -- etldoc: water_z10 -> layer_water:z10 + SELECT * + FROM water_z10 + WHERE zoom_level = 10 + UNION ALL + -- etldoc: water_z11 -> layer_water:z11 + SELECT * + FROM water_z11 + WHERE zoom_level = 11 + UNION ALL + -- etldoc: water_z12 -> layer_water:z12 + SELECT * + FROM water_z12 + WHERE zoom_level = 12 + UNION ALL + -- etldoc: water_z13 -> layer_water:z13 + SELECT * + FROM water_z13 + WHERE zoom_level = 13 + UNION ALL + -- etldoc: water_z14 -> layer_water:z14_ + SELECT * + FROM water_z14 + WHERE zoom_level >= 14 + ) AS zoom_levels +WHERE geometry && bbox; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/water/water.yaml b/layers/water/water.yaml index 24ecabe..cbd0a07 100644 --- a/layers/water/water.yaml +++ b/layers/water/water.yaml @@ -34,6 +34,7 @@ layer: datasource: query: (SELECT geometry, class, intermittent, brunnel FROM layer_water(!bbox!, z(!scale_denominator!))) AS t schema: + - ./update_water.sql - ./water.sql datasources: - type: imposm3 diff --git a/layers/water_name/layer.sql b/layers/water_name/layer.sql index 0aab292..2327a05 100644 --- a/layers/water_name/layer.sql +++ b/layers/water_name/layer.sql @@ -1,59 +1,79 @@ - -- etldoc: layer_water_name[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_water_name | z0_8 | z9_13 | z14+" ] ; CREATE OR REPLACE FUNCTION layer_water_name(bbox geometry, zoom_level integer) -RETURNS TABLE(osm_id bigint, geometry geometry, name text, name_en text, name_de text, tags hstore, class text, intermittent int) AS $$ + RETURNS TABLE + ( + osm_id bigint, + geometry geometry, + name text, + name_en text, + name_de text, + tags hstore, + class text, + intermittent int + ) +AS +$$ +SELECT -- etldoc: osm_water_lakeline -> layer_water_name:z9_13 -- etldoc: osm_water_lakeline -> layer_water_name:z14_ - SELECT - CASE WHEN osm_id<0 THEN -osm_id*10+4 - ELSE osm_id*10+1 - END AS osm_id_hash, - geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, + CASE + WHEN osm_id < 0 THEN -osm_id * 10 + 4 + ELSE osm_id * 10 + 1 + END AS osm_id_hash, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, tags, - 'lake'::text AS class, - is_intermittent::int AS intermittent - FROM osm_water_lakeline - WHERE geometry && bbox - AND ((zoom_level BETWEEN 9 AND 13 AND LineLabel(zoom_level, NULLIF(name, ''), geometry)) - OR (zoom_level >= 14)) + 'lake'::text AS class, + is_intermittent::int AS intermittent +FROM osm_water_lakeline +WHERE geometry && bbox + AND ((zoom_level BETWEEN 9 AND 13 AND LineLabel(zoom_level, NULLIF(name, ''), geometry)) + OR (zoom_level >= 14)) +UNION ALL +SELECT -- etldoc: osm_water_point -> layer_water_name:z9_13 -- etldoc: osm_water_point -> layer_water_name:z14_ - UNION ALL - SELECT - CASE WHEN osm_id<0 THEN -osm_id*10+4 - ELSE osm_id*10+1 - END AS osm_id_hash, - geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, + CASE + WHEN osm_id < 0 THEN -osm_id * 10 + 4 + ELSE osm_id * 10 + 1 + END AS osm_id_hash, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, tags, - 'lake'::text AS class, - is_intermittent::int AS intermittent - FROM osm_water_point - WHERE geometry && bbox AND ( - (zoom_level BETWEEN 9 AND 13 AND area > 70000*2^(20-zoom_level)) + 'lake'::text AS class, + is_intermittent::int AS intermittent +FROM osm_water_point +WHERE geometry && bbox + AND ( + (zoom_level BETWEEN 9 AND 13 AND area > 70000 * 2 ^ (20 - zoom_level)) OR (zoom_level >= 14) ) +UNION ALL +SELECT -- etldoc: osm_marine_point -> layer_water_name:z0_8 -- etldoc: osm_marine_point -> layer_water_name:z9_13 -- etldoc: osm_marine_point -> layer_water_name:z14_ - UNION ALL - SELECT osm_id*10, geometry, name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, + osm_id * 10 AS osm_id_hash, + geometry, + name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, tags, - place::text AS class, - is_intermittent::int AS intermittent - FROM osm_marine_point - WHERE geometry && bbox AND ( + place::text AS class, + is_intermittent::int AS intermittent +FROM osm_marine_point +WHERE geometry && bbox + AND ( place = 'ocean' OR (zoom_level >= "rank" AND "rank" IS NOT NULL) OR (zoom_level >= 8) ); -$$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/layers/water_name/update_marine_point.sql b/layers/water_name/update_marine_point.sql index c33a506..8fec8d0 100644 --- a/layers/water_name/update_marine_point.sql +++ b/layers/water_name/update_marine_point.sql @@ -3,67 +3,77 @@ DROP TRIGGER IF EXISTS trigger_refresh ON water_name_marine.updates; CREATE EXTENSION IF NOT EXISTS unaccent; -CREATE OR REPLACE FUNCTION update_osm_marine_point() RETURNS VOID AS $$ +CREATE OR REPLACE FUNCTION update_osm_marine_point() RETURNS void AS +$$ BEGIN - -- etldoc: osm_marine_point -> osm_marine_point - UPDATE osm_marine_point AS osm SET "rank" = NULL WHERE "rank" IS NOT NULL; + -- etldoc: osm_marine_point -> osm_marine_point + UPDATE osm_marine_point AS osm SET "rank" = NULL WHERE "rank" IS NOT NULL; - -- etldoc: ne_10m_geography_marine_polys -> osm_marine_point - -- etldoc: osm_marine_point -> osm_marine_point + -- etldoc: ne_10m_geography_marine_polys -> osm_marine_point + -- etldoc: osm_marine_point -> osm_marine_point - WITH important_marine_point AS ( - SELECT osm.geometry, osm.osm_id, osm.name, osm.name_en, ne.scalerank, osm.is_intermittent - FROM ne_10m_geography_marine_polys AS ne, osm_marine_point AS osm - WHERE trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) ILIKE osm.name - OR trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) ILIKE osm.tags->'name:en' - OR trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) ILIKE osm.tags->'name:es' - OR osm.name ILIKE trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) || ' %' - ) - UPDATE osm_marine_point AS osm - SET "rank" = scalerank - FROM important_marine_point AS ne - WHERE osm.osm_id = ne.osm_id; + WITH important_marine_point AS ( + SELECT osm.geometry, osm.osm_id, osm.name, osm.name_en, ne.scalerank, osm.is_intermittent + FROM ne_10m_geography_marine_polys AS ne, + osm_marine_point AS osm + WHERE trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) ILIKE osm.name + OR trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) ILIKE osm.tags->'name:en' + OR trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) ILIKE osm.tags->'name:es' + OR osm.name ILIKE trim(regexp_replace(ne.name, '\\s+', ' ', 'g')) || ' %' + ) + UPDATE osm_marine_point AS osm + SET "rank" = scalerank + FROM important_marine_point AS ne + WHERE osm.osm_id = ne.osm_id; - UPDATE osm_marine_point - SET tags = update_tags(tags, geometry) - WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; + UPDATE osm_marine_point + SET tags = update_tags(tags, geometry) + WHERE COALESCE(tags->'name:latin', tags->'name:nonlatin', tags->'name_int') IS NULL; END; $$ LANGUAGE plpgsql; SELECT update_osm_marine_point(); -CREATE INDEX IF NOT EXISTS osm_marine_point_rank_idx ON osm_marine_point("rank"); +CREATE INDEX IF NOT EXISTS osm_marine_point_rank_idx ON osm_marine_point ("rank"); -- Handle updates CREATE SCHEMA IF NOT EXISTS water_name_marine; -CREATE TABLE IF NOT EXISTS water_name_marine.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION water_name_marine.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS water_name_marine.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION water_name_marine.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO water_name_marine.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO water_name_marine.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION water_name_marine.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh water_name_marine rank'; PERFORM update_osm_marine_point(); + -- noinspection SqlWithoutWhere DELETE FROM water_name_marine.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_marine_point + AFTER INSERT OR UPDATE OR DELETE + ON osm_marine_point FOR EACH STATEMENT - EXECUTE PROCEDURE water_name_marine.flag(); +EXECUTE PROCEDURE water_name_marine.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON water_name_marine.updates + AFTER INSERT + ON water_name_marine.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE water_name_marine.refresh(); +EXECUTE PROCEDURE water_name_marine.refresh(); diff --git a/layers/water_name/update_water_lakeline.sql b/layers/water_name/update_water_lakeline.sql index b4ccb56..3c58e43 100644 --- a/layers/water_name/update_water_lakeline.sql +++ b/layers/water_name/update_water_lakeline.sql @@ -3,76 +3,89 @@ DROP TRIGGER IF EXISTS trigger_update_line ON osm_water_polygon; DROP TRIGGER IF EXISTS trigger_insert_line ON osm_water_polygon; CREATE OR REPLACE VIEW osm_water_lakeline_view AS - SELECT wp.osm_id, - ll.wkb_geometry AS geometry, - name, name_en, name_de, - update_tags(tags, ll.wkb_geometry) AS tags, - ST_Area(wp.geometry) AS area, - is_intermittent - FROM osm_water_polygon AS wp - INNER JOIN lake_centerline ll ON wp.osm_id = ll.osm_id - WHERE wp.name <> '' AND ST_IsValid(wp.geometry) -; +SELECT wp.osm_id, + ll.wkb_geometry AS geometry, + name, + name_en, + name_de, + update_tags(tags, ll.wkb_geometry) AS tags, + ST_Area(wp.geometry) AS area, + is_intermittent +FROM osm_water_polygon AS wp + INNER JOIN lake_centerline ll ON wp.osm_id = ll.osm_id +WHERE wp.name <> '' + AND ST_IsValid(wp.geometry); -- etldoc: osm_water_polygon -> osm_water_lakeline -- etldoc: lake_centerline -> osm_water_lakeline CREATE TABLE IF NOT EXISTS osm_water_lakeline AS -SELECT * FROM osm_water_lakeline_view; -DO $$ +SELECT * +FROM osm_water_lakeline_view; +DO +$$ BEGIN - ALTER TABLE osm_water_lakeline ADD CONSTRAINT osm_water_lakeline_pk PRIMARY KEY (osm_id); - EXCEPTION WHEN others then - RAISE NOTICE 'primary key osm_water_lakeline_pk already exists in osm_water_lakeline.'; + ALTER TABLE osm_water_lakeline + ADD CONSTRAINT osm_water_lakeline_pk PRIMARY KEY (osm_id); + EXCEPTION + WHEN OTHERS THEN + RAISE NOTICE 'primary key osm_water_lakeline_pk already exists in osm_water_lakeline.'; END; $$; -CREATE INDEX IF NOT EXISTS osm_water_lakeline_geometry_idx ON osm_water_lakeline USING gist(geometry); +CREATE INDEX IF NOT EXISTS osm_water_lakeline_geometry_idx ON osm_water_lakeline USING gist (geometry); -- Handle updates CREATE SCHEMA IF NOT EXISTS water_lakeline; -CREATE OR REPLACE FUNCTION water_lakeline.delete() RETURNS trigger AS $BODY$ +CREATE OR REPLACE FUNCTION water_lakeline.delete() RETURNS trigger AS +$$ BEGIN - DELETE FROM osm_water_lakeline - WHERE osm_water_lakeline.osm_id = OLD.osm_id ; + DELETE + FROM osm_water_lakeline + WHERE osm_water_lakeline.osm_id = OLD.osm_id; - RETURN null; + RETURN NULL; END; -$BODY$ language plpgsql; +$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION water_lakeline.update() RETURNS trigger AS $BODY$ +CREATE OR REPLACE FUNCTION water_lakeline.update() RETURNS trigger AS +$$ BEGIN UPDATE osm_water_lakeline SET (osm_id, geometry, name, name_en, name_de, tags, area, is_intermittent) = - (SELECT * FROM osm_water_lakeline_view WHERE osm_water_lakeline_view.osm_id = NEW.osm_id) + (SELECT * FROM osm_water_lakeline_view WHERE osm_water_lakeline_view.osm_id = NEW.osm_id) WHERE osm_water_lakeline.osm_id = NEW.osm_id; - RETURN null; + RETURN NULL; END; -$BODY$ language plpgsql; +$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION water_lakeline.insert() RETURNS trigger AS $BODY$ +CREATE OR REPLACE FUNCTION water_lakeline.insert() RETURNS trigger AS +$$ BEGIN INSERT INTO osm_water_lakeline SELECT * FROM osm_water_lakeline_view WHERE osm_water_lakeline_view.osm_id = NEW.osm_id; - RETURN null; + RETURN NULL; END; -$BODY$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_delete_line - AFTER DELETE ON osm_water_polygon + AFTER DELETE + ON osm_water_polygon FOR EACH ROW - EXECUTE PROCEDURE water_lakeline.delete(); +EXECUTE PROCEDURE water_lakeline.delete(); CREATE TRIGGER trigger_update_line - AFTER UPDATE ON osm_water_polygon + AFTER UPDATE + ON osm_water_polygon FOR EACH ROW - EXECUTE PROCEDURE water_lakeline.update(); +EXECUTE PROCEDURE water_lakeline.update(); CREATE TRIGGER trigger_insert_line - AFTER INSERT ON osm_water_polygon + AFTER INSERT + ON osm_water_polygon FOR EACH ROW - EXECUTE PROCEDURE water_lakeline.insert(); +EXECUTE PROCEDURE water_lakeline.insert(); diff --git a/layers/water_name/update_water_point.sql b/layers/water_name/update_water_point.sql index b8445b7..b954bfc 100644 --- a/layers/water_name/update_water_point.sql +++ b/layers/water_name/update_water_point.sql @@ -3,26 +3,32 @@ DROP TRIGGER IF EXISTS trigger_update_point ON osm_water_polygon; DROP TRIGGER IF EXISTS trigger_insert_point ON osm_water_polygon; CREATE OR REPLACE VIEW osm_water_point_view AS - SELECT - wp.osm_id, ST_PointOnSurface(wp.geometry) AS geometry, - wp.name, wp.name_en, wp.name_de, - update_tags(wp.tags, ST_PointOnSurface(wp.geometry)) AS tags, - ST_Area(wp.geometry) AS area, - wp.is_intermittent - FROM osm_water_polygon AS wp - LEFT JOIN lake_centerline ll ON wp.osm_id = ll.osm_id - WHERE ll.osm_id IS NULL AND wp.name <> '' -; +SELECT wp.osm_id, + ST_PointOnSurface(wp.geometry) AS geometry, + wp.name, + wp.name_en, + wp.name_de, + update_tags(wp.tags, ST_PointOnSurface(wp.geometry)) AS tags, + ST_Area(wp.geometry) AS area, + wp.is_intermittent +FROM osm_water_polygon AS wp + LEFT JOIN lake_centerline ll ON wp.osm_id = ll.osm_id +WHERE ll.osm_id IS NULL + AND wp.name <> ''; -- etldoc: osm_water_polygon -> osm_water_point -- etldoc: lake_centerline -> osm_water_point CREATE TABLE IF NOT EXISTS osm_water_point AS -SELECT * FROM osm_water_point_view; -DO $$ +SELECT * +FROM osm_water_point_view; +DO +$$ BEGIN - ALTER TABLE osm_water_point ADD CONSTRAINT osm_water_point_pk PRIMARY KEY (osm_id); - EXCEPTION WHEN others then - RAISE NOTICE 'primary key osm_water_point_pk already exists in osm_water_point.'; + ALTER TABLE osm_water_point + ADD CONSTRAINT osm_water_point_pk PRIMARY KEY (osm_id); + EXCEPTION + WHEN OTHERS THEN + RAISE NOTICE 'primary key osm_water_point_pk already exists in osm_water_point.'; END; $$; CREATE INDEX IF NOT EXISTS osm_water_point_geometry_idx ON osm_water_point USING gist (geometry); @@ -31,48 +37,55 @@ CREATE INDEX IF NOT EXISTS osm_water_point_geometry_idx ON osm_water_point USING CREATE SCHEMA IF NOT EXISTS water_point; -CREATE OR REPLACE FUNCTION water_point.delete() RETURNS trigger AS $BODY$ +CREATE OR REPLACE FUNCTION water_point.delete() RETURNS trigger AS +$$ BEGIN - DELETE FROM osm_water_point - WHERE osm_water_point.osm_id = OLD.osm_id ; + DELETE + FROM osm_water_point + WHERE osm_water_point.osm_id = OLD.osm_id; - RETURN null; + RETURN NULL; END; -$BODY$ language plpgsql; +$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION water_point.update() RETURNS trigger AS $BODY$ +CREATE OR REPLACE FUNCTION water_point.update() RETURNS trigger AS +$$ BEGIN UPDATE osm_water_point SET (osm_id, geometry, name, name_en, name_de, tags, area, is_intermittent) = - (SELECT * FROM osm_water_point_view WHERE osm_water_point_view.osm_id = NEW.osm_id) + (SELECT * FROM osm_water_point_view WHERE osm_water_point_view.osm_id = NEW.osm_id) WHERE osm_water_point.osm_id = NEW.osm_id; - RETURN null; + RETURN NULL; END; -$BODY$ language plpgsql; +$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION water_point.insert() RETURNS trigger AS $BODY$ +CREATE OR REPLACE FUNCTION water_point.insert() RETURNS trigger AS +$$ BEGIN INSERT INTO osm_water_point SELECT * FROM osm_water_point_view WHERE osm_water_point_view.osm_id = NEW.osm_id; - RETURN null; + RETURN NULL; END; -$BODY$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_delete_point - AFTER DELETE ON osm_water_polygon + AFTER DELETE + ON osm_water_polygon FOR EACH ROW - EXECUTE PROCEDURE water_point.delete(); +EXECUTE PROCEDURE water_point.delete(); CREATE TRIGGER trigger_update_point - AFTER UPDATE ON osm_water_polygon + AFTER UPDATE + ON osm_water_polygon FOR EACH ROW - EXECUTE PROCEDURE water_point.update(); +EXECUTE PROCEDURE water_point.update(); CREATE TRIGGER trigger_insert_point - AFTER INSERT ON osm_water_polygon + AFTER INSERT + ON osm_water_polygon FOR EACH ROW - EXECUTE PROCEDURE water_point.insert(); +EXECUTE PROCEDURE water_point.insert(); diff --git a/layers/waterway/update_important_waterway.sql b/layers/waterway/update_important_waterway.sql index 43227cf..51cace4 100644 --- a/layers/waterway/update_important_waterway.sql +++ b/layers/waterway/update_important_waterway.sql @@ -7,185 +7,227 @@ DROP TRIGGER IF EXISTS trigger_refresh ON waterway_important.updates; -- and also makes it possible to filter out too short rivers CREATE INDEX IF NOT EXISTS osm_waterway_linestring_waterway_partial_idx - ON osm_waterway_linestring(waterway) + ON osm_waterway_linestring (waterway) WHERE waterway = 'river'; CREATE INDEX IF NOT EXISTS osm_waterway_linestring_name_partial_idx - ON osm_waterway_linestring(name) + ON osm_waterway_linestring (name) WHERE name <> ''; -- etldoc: osm_waterway_linestring -> osm_important_waterway_linestring CREATE TABLE IF NOT EXISTS osm_important_waterway_linestring AS - SELECT - (ST_Dump(geometry)).geom AS geometry, - name, name_en, name_de, tags - FROM ( - SELECT - ST_LineMerge(ST_Union(geometry)) AS geometry, - name, name_en, name_de, slice_language_tags(tags) AS tags - FROM osm_waterway_linestring - WHERE name <> '' AND waterway = 'river' AND ST_IsValid(geometry) - GROUP BY name, name_en, name_de, slice_language_tags(tags) - ) AS waterway_union; -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_names ON osm_important_waterway_linestring(name); -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_geometry_idx ON osm_important_waterway_linestring USING gist(geometry); +SELECT (ST_Dump(geometry)).geom AS geometry, + name, + name_en, + name_de, + tags +FROM ( + SELECT ST_LineMerge(ST_Union(geometry)) AS geometry, + name, + name_en, + name_de, + slice_language_tags(tags) AS tags + FROM osm_waterway_linestring + WHERE name <> '' + AND waterway = 'river' + AND ST_IsValid(geometry) + GROUP BY name, name_en, name_de, slice_language_tags(tags) + ) AS waterway_union; +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_names ON osm_important_waterway_linestring (name); +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_geometry_idx ON osm_important_waterway_linestring USING gist (geometry); -- etldoc: osm_important_waterway_linestring -> osm_important_waterway_linestring_gen1 CREATE OR REPLACE VIEW osm_important_waterway_linestring_gen1_view AS - SELECT ST_Simplify(geometry, 60) AS geometry, name, name_en, name_de, tags - FROM osm_important_waterway_linestring - WHERE ST_Length(geometry) > 1000 -; +SELECT ST_Simplify(geometry, 60) AS geometry, name, name_en, name_de, tags +FROM osm_important_waterway_linestring +WHERE ST_Length(geometry) > 1000; + CREATE TABLE IF NOT EXISTS osm_important_waterway_linestring_gen1 AS -SELECT * FROM osm_important_waterway_linestring_gen1_view; -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen1_name_idx ON osm_important_waterway_linestring_gen1(name); -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen1_geometry_idx ON osm_important_waterway_linestring_gen1 USING gist(geometry); +SELECT * +FROM osm_important_waterway_linestring_gen1_view; +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen1_name_idx ON osm_important_waterway_linestring_gen1 (name); +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen1_geometry_idx ON osm_important_waterway_linestring_gen1 USING gist (geometry); -- etldoc: osm_important_waterway_linestring_gen1 -> osm_important_waterway_linestring_gen2 CREATE OR REPLACE VIEW osm_important_waterway_linestring_gen2_view AS - SELECT ST_Simplify(geometry, 100) AS geometry, name, name_en, name_de, tags - FROM osm_important_waterway_linestring_gen1 - WHERE ST_Length(geometry) > 4000 -; +SELECT ST_Simplify(geometry, 100) AS geometry, name, name_en, name_de, tags +FROM osm_important_waterway_linestring_gen1 +WHERE ST_Length(geometry) > 4000; + CREATE TABLE IF NOT EXISTS osm_important_waterway_linestring_gen2 AS -SELECT * FROM osm_important_waterway_linestring_gen2_view; -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen2_name_idx ON osm_important_waterway_linestring_gen2(name); -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen2_geometry_idx ON osm_important_waterway_linestring_gen2 USING gist(geometry); +SELECT * +FROM osm_important_waterway_linestring_gen2_view; +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen2_name_idx ON osm_important_waterway_linestring_gen2 (name); +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen2_geometry_idx ON osm_important_waterway_linestring_gen2 USING gist (geometry); -- etldoc: osm_important_waterway_linestring_gen2 -> osm_important_waterway_linestring_gen3 CREATE OR REPLACE VIEW osm_important_waterway_linestring_gen3_view AS - SELECT ST_Simplify(geometry, 200) AS geometry, name, name_en, name_de, tags - FROM osm_important_waterway_linestring_gen2 - WHERE ST_Length(geometry) > 8000 -; +SELECT ST_Simplify(geometry, 200) AS geometry, name, name_en, name_de, tags +FROM osm_important_waterway_linestring_gen2 +WHERE ST_Length(geometry) > 8000; + CREATE TABLE IF NOT EXISTS osm_important_waterway_linestring_gen3 AS -SELECT * FROM osm_important_waterway_linestring_gen3_view; -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen3_name_idx ON osm_important_waterway_linestring_gen3(name); -CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen3_geometry_idx ON osm_important_waterway_linestring_gen3 USING gist(geometry); +SELECT * +FROM osm_important_waterway_linestring_gen3_view; +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen3_name_idx ON osm_important_waterway_linestring_gen3 (name); +CREATE INDEX IF NOT EXISTS osm_important_waterway_linestring_gen3_geometry_idx ON osm_important_waterway_linestring_gen3 USING gist (geometry); -- Handle updates CREATE SCHEMA IF NOT EXISTS waterway_important; -CREATE TABLE IF NOT EXISTS waterway_important.changes( - id serial primary key, - is_old boolean, - name character varying, +CREATE TABLE IF NOT EXISTS waterway_important.changes +( + id serial PRIMARY KEY, + is_old boolean, + name character varying, name_en character varying, name_de character varying, - tags hstore, - unique (is_old, name, name_en, name_de, tags) + tags hstore, + UNIQUE (is_old, name, name_en, name_de, tags) ); -CREATE OR REPLACE FUNCTION waterway_important.store() RETURNS trigger AS $$ +CREATE OR REPLACE FUNCTION waterway_important.store() RETURNS trigger AS +$$ BEGIN - IF (TG_OP IN ('DELETE', 'UPDATE')) AND OLD.name <> '' AND OLD.waterway = 'river' THEN + IF (tg_op IN ('DELETE', 'UPDATE')) AND OLD.name <> '' AND OLD.waterway = 'river' THEN INSERT INTO waterway_important.changes(is_old, name, name_en, name_de, tags) - VALUES (true, OLD.name, OLD.name_en, OLD.name_de, slice_language_tags(OLD.tags)) + VALUES (TRUE, OLD.name, OLD.name_en, OLD.name_de, slice_language_tags(OLD.tags)) ON CONFLICT(is_old, name, name_en, name_de, tags) DO NOTHING; END IF; - IF (TG_OP IN ('UPDATE', 'INSERT')) AND NEW.name <> '' AND NEW.waterway = 'river' THEN + IF (tg_op IN ('UPDATE', 'INSERT')) AND NEW.name <> '' AND NEW.waterway = 'river' THEN INSERT INTO waterway_important.changes(is_old, name, name_en, name_de, tags) - VALUES (false, NEW.name, NEW.name_en, NEW.name_de, slice_language_tags(NEW.tags)) + VALUES (FALSE, NEW.name, NEW.name_en, NEW.name_de, slice_language_tags(NEW.tags)) ON CONFLICT(is_old, name, name_en, name_de, tags) DO NOTHING; END IF; RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; -CREATE TABLE IF NOT EXISTS waterway_important.updates(id serial primary key, t text, unique (t)); -CREATE OR REPLACE FUNCTION waterway_important.flag() RETURNS trigger AS $$ +CREATE TABLE IF NOT EXISTS waterway_important.updates +( + id serial PRIMARY KEY, + t text, + UNIQUE (t) +); +CREATE OR REPLACE FUNCTION waterway_important.flag() RETURNS trigger AS +$$ BEGIN - INSERT INTO waterway_important.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; - RETURN null; + INSERT INTO waterway_important.updates(t) VALUES ('y') ON CONFLICT(t) DO NOTHING; + RETURN NULL; END; -$$ language plpgsql; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION waterway_important.refresh() RETURNS trigger AS - $BODY$ - BEGIN +$$ +BEGIN RAISE LOG 'Refresh waterway'; -- REFRESH osm_important_waterway_linestring - DELETE FROM osm_important_waterway_linestring AS w - USING waterway_important.changes AS c - WHERE - c.is_old AND - w.name = c.name AND w.name_en IS NOT DISTINCT FROM c.name_en AND w.name_de IS NOT DISTINCT FROM c.name_de AND w.tags IS NOT DISTINCT FROM c.tags; + DELETE + FROM osm_important_waterway_linestring AS w + USING waterway_important.changes AS c + WHERE c.is_old + AND w.name = c.name + AND w.name_en IS NOT DISTINCT FROM c.name_en + AND w.name_de IS NOT DISTINCT FROM c.name_de + AND w.tags IS NOT DISTINCT FROM c.tags; INSERT INTO osm_important_waterway_linestring - SELECT - (ST_Dump(geometry)).geom AS geometry, - name, name_en, name_de, tags + SELECT (ST_Dump(geometry)).geom AS geometry, + name, + name_en, + name_de, + tags FROM ( - SELECT - ST_LineMerge(ST_Union(geometry)) AS geometry, - w.name, w.name_en, w.name_de, slice_language_tags(w.tags) AS tags - FROM osm_waterway_linestring AS w - JOIN waterway_important.changes AS c ON - w.name = c.name AND w.name_en IS NOT DISTINCT FROM c.name_en AND w.name_de IS NOT DISTINCT FROM c.name_de AND slice_language_tags(w.tags) IS NOT DISTINCT FROM c.tags - WHERE w.name <> '' AND w.waterway = 'river' AND ST_IsValid(geometry) AND - NOT c.is_old - GROUP BY w.name, w.name_en, w.name_de, slice_language_tags(w.tags) - ) AS waterway_union; + SELECT ST_LineMerge(ST_Union(geometry)) AS geometry, + w.name, + w.name_en, + w.name_de, + slice_language_tags(w.tags) AS tags + FROM osm_waterway_linestring AS w + JOIN waterway_important.changes AS c ON + w.name = c.name AND w.name_en IS NOT DISTINCT FROM c.name_en AND + w.name_de IS NOT DISTINCT FROM c.name_de AND + slice_language_tags(w.tags) IS NOT DISTINCT FROM c.tags + WHERE w.name <> '' + AND w.waterway = 'river' + AND ST_IsValid(geometry) + AND NOT c.is_old + GROUP BY w.name, w.name_en, w.name_de, slice_language_tags(w.tags) + ) AS waterway_union; -- REFRESH sm_important_waterway_linestring_gen1 - DELETE FROM osm_important_waterway_linestring_gen1 AS w - USING waterway_important.changes AS c - WHERE - c.is_old AND - w.name = c.name AND w.name_en IS NOT DISTINCT FROM c.name_en AND w.name_de IS NOT DISTINCT FROM c.name_de AND w.tags IS NOT DISTINCT FROM c.tags; + DELETE + FROM osm_important_waterway_linestring_gen1 AS w + USING waterway_important.changes AS c + WHERE c.is_old + AND w.name = c.name + AND w.name_en IS NOT DISTINCT FROM c.name_en + AND w.name_de IS NOT DISTINCT FROM c.name_de + AND w.tags IS NOT DISTINCT FROM c.tags; INSERT INTO osm_important_waterway_linestring_gen1 SELECT w.* FROM osm_important_waterway_linestring_gen1_view AS w - NATURAL JOIN waterway_important.changes AS c + NATURAL JOIN waterway_important.changes AS c WHERE NOT c.is_old; -- REFRESH osm_important_waterway_linestring_gen2 - DELETE FROM osm_important_waterway_linestring_gen2 AS w - USING waterway_important.changes AS c - WHERE - c.is_old AND - w.name = c.name AND w.name_en IS NOT DISTINCT FROM c.name_en AND w.name_de IS NOT DISTINCT FROM c.name_de AND w.tags IS NOT DISTINCT FROM c.tags; + DELETE + FROM osm_important_waterway_linestring_gen2 AS w + USING waterway_important.changes AS c + WHERE c.is_old + AND w.name = c.name + AND w.name_en IS NOT DISTINCT FROM c.name_en + AND w.name_de IS NOT DISTINCT FROM c.name_de + AND w.tags IS NOT DISTINCT FROM c.tags; INSERT INTO osm_important_waterway_linestring_gen2 SELECT w.* FROM osm_important_waterway_linestring_gen2_view AS w - NATURAL JOIN waterway_important.changes AS c + NATURAL JOIN waterway_important.changes AS c WHERE NOT c.is_old; -- REFRESH osm_important_waterway_linestring_gen3 - DELETE FROM osm_important_waterway_linestring_gen3 AS w - USING waterway_important.changes AS c - WHERE - c.is_old AND - w.name = c.name AND w.name_en IS NOT DISTINCT FROM c.name_en AND w.name_de IS NOT DISTINCT FROM c.name_de AND w.tags IS NOT DISTINCT FROM c.tags; + DELETE + FROM osm_important_waterway_linestring_gen3 AS w + USING waterway_important.changes AS c + WHERE c.is_old + AND w.name = c.name + AND w.name_en IS NOT DISTINCT FROM c.name_en + AND w.name_de IS NOT DISTINCT FROM c.name_de + AND w.tags IS NOT DISTINCT FROM c.tags; INSERT INTO osm_important_waterway_linestring_gen3 SELECT w.* FROM osm_important_waterway_linestring_gen3_view AS w - NATURAL JOIN waterway_important.changes AS c + NATURAL JOIN waterway_important.changes AS c WHERE NOT c.is_old; + -- noinspection SqlWithoutWhere DELETE FROM waterway_important.changes; + -- noinspection SqlWithoutWhere DELETE FROM waterway_important.updates; - RETURN null; - END; - $BODY$ -language plpgsql; + + RETURN NULL; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_store - AFTER INSERT OR UPDATE OR DELETE ON osm_waterway_linestring + AFTER INSERT OR UPDATE OR DELETE + ON osm_waterway_linestring FOR EACH ROW - EXECUTE PROCEDURE waterway_important.store(); +EXECUTE PROCEDURE waterway_important.store(); CREATE TRIGGER trigger_flag - AFTER INSERT OR UPDATE OR DELETE ON osm_waterway_linestring + AFTER INSERT OR UPDATE OR DELETE + ON osm_waterway_linestring FOR EACH STATEMENT - EXECUTE PROCEDURE waterway_important.flag(); +EXECUTE PROCEDURE waterway_important.flag(); CREATE CONSTRAINT TRIGGER trigger_refresh - AFTER INSERT ON waterway_important.updates + AFTER INSERT + ON waterway_important.updates INITIALLY DEFERRED FOR EACH ROW - EXECUTE PROCEDURE waterway_important.refresh(); +EXECUTE PROCEDURE waterway_important.refresh(); diff --git a/layers/waterway/update_waterway_linestring.sql b/layers/waterway/update_waterway_linestring.sql index e94c8c5..f23f6cd 100644 --- a/layers/waterway/update_waterway_linestring.sql +++ b/layers/waterway/update_waterway_linestring.sql @@ -1,36 +1,38 @@ DROP TRIGGER IF EXISTS trigger_flag ON osm_waterway_linestring; DROP TRIGGER IF EXISTS trigger_refresh ON osm_waterway_linestring; -DO $$ -BEGIN - update osm_waterway_linestring - SET tags = update_tags(tags, geometry); +DO +$$ + BEGIN + UPDATE osm_waterway_linestring + SET tags = update_tags(tags, geometry); - update osm_waterway_linestring_gen1 - SET tags = update_tags(tags, geometry); + UPDATE osm_waterway_linestring_gen1 + SET tags = update_tags(tags, geometry); - update osm_waterway_linestring_gen2 - SET tags = update_tags(tags, geometry); + UPDATE osm_waterway_linestring_gen2 + SET tags = update_tags(tags, geometry); - update osm_waterway_linestring_gen3 - SET tags = update_tags(tags, geometry); -END $$; + UPDATE osm_waterway_linestring_gen3 + SET tags = update_tags(tags, geometry); + END +$$; -- Handle updates CREATE SCHEMA IF NOT EXISTS waterway_linestring; CREATE OR REPLACE FUNCTION waterway_linestring.refresh() RETURNS trigger AS - $BODY$ - BEGIN --- RAISE NOTICE 'Refresh waterway_linestring %', NEW.osm_id; +$$ +BEGIN + -- RAISE NOTICE 'Refresh waterway_linestring %', NEW.osm_id; NEW.tags = update_tags(NEW.tags, NEW.geometry); RETURN NEW; - END; - $BODY$ -language plpgsql; +END; +$$ LANGUAGE plpgsql; CREATE TRIGGER trigger_refresh - BEFORE INSERT OR UPDATE ON osm_waterway_linestring + BEFORE INSERT OR UPDATE + ON osm_waterway_linestring FOR EACH ROW - EXECUTE PROCEDURE waterway_linestring.refresh(); +EXECUTE PROCEDURE waterway_linestring.refresh(); diff --git a/layers/waterway/waterway.sql b/layers/waterway/waterway.sql index 35c277f..36e5ca2 100644 --- a/layers/waterway/waterway.sql +++ b/layers/waterway/waterway.sql @@ -1,112 +1,225 @@ -CREATE OR REPLACE FUNCTION waterway_brunnel(is_bridge BOOL, is_tunnel BOOL) RETURNS TEXT AS $$ - SELECT CASE - WHEN is_bridge THEN 'bridge' - WHEN is_tunnel THEN 'tunnel' - END; +CREATE OR REPLACE FUNCTION waterway_brunnel(is_bridge bool, is_tunnel bool) RETURNS text AS $$ -LANGUAGE SQL -IMMUTABLE STRICT PARALLEL SAFE; +SELECT CASE + WHEN is_bridge THEN 'bridge' + WHEN is_tunnel THEN 'tunnel' + END; +$$ LANGUAGE SQL IMMUTABLE + STRICT + PARALLEL SAFE; -- etldoc: ne_110m_rivers_lake_centerlines -> waterway_z3 -CREATE OR REPLACE VIEW waterway_z3 AS ( - SELECT geometry, 'river'::text AS class, NULL::text AS name, NULL::text AS name_en, NULL::text AS name_de, NULL::hstore AS tags, NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, NULL::boolean AS is_intermittent - FROM ne_110m_rivers_lake_centerlines - WHERE featurecla = 'River' -); +CREATE OR REPLACE VIEW waterway_z3 AS +( +SELECT geometry, + 'river'::text AS class, + NULL::text AS name, + NULL::text AS name_en, + NULL::text AS name_de, + NULL::hstore AS tags, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_intermittent +FROM ne_110m_rivers_lake_centerlines +WHERE featurecla = 'River' + ); -- etldoc: ne_50m_rivers_lake_centerlines -> waterway_z4 -CREATE OR REPLACE VIEW waterway_z4 AS ( - SELECT geometry, 'river'::text AS class, NULL::text AS name, NULL::text AS name_en, NULL::text AS name_de, NULL::hstore AS tags, NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, NULL::boolean AS is_intermittent - FROM ne_50m_rivers_lake_centerlines - WHERE featurecla = 'River' -); +CREATE OR REPLACE VIEW waterway_z4 AS +( +SELECT geometry, + 'river'::text AS class, + NULL::text AS name, + NULL::text AS name_en, + NULL::text AS name_de, + NULL::hstore AS tags, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_intermittent +FROM ne_50m_rivers_lake_centerlines +WHERE featurecla = 'River' + ); -- etldoc: ne_10m_rivers_lake_centerlines -> waterway_z6 -CREATE OR REPLACE VIEW waterway_z6 AS ( - SELECT geometry, 'river'::text AS class, NULL::text AS name, NULL::text AS name_en, NULL::text AS name_de, NULL::hstore AS tags, NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, NULL::boolean AS is_intermittent - FROM ne_10m_rivers_lake_centerlines - WHERE featurecla = 'River' -); +CREATE OR REPLACE VIEW waterway_z6 AS +( +SELECT geometry, + 'river'::text AS class, + NULL::text AS name, + NULL::text AS name_en, + NULL::text AS name_de, + NULL::hstore AS tags, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_intermittent +FROM ne_10m_rivers_lake_centerlines +WHERE featurecla = 'River' + ); -- etldoc: osm_important_waterway_linestring_gen3 -> waterway_z9 -CREATE OR REPLACE VIEW waterway_z9 AS ( - SELECT geometry, 'river'::text AS class, name, name_en, name_de, tags, NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, NULL::boolean AS is_intermittent - FROM osm_important_waterway_linestring_gen3 -); +CREATE OR REPLACE VIEW waterway_z9 AS +( +SELECT geometry, + 'river'::text AS class, + name, + name_en, + name_de, + tags, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_intermittent +FROM osm_important_waterway_linestring_gen3 + ); -- etldoc: osm_important_waterway_linestring_gen2 -> waterway_z10 -CREATE OR REPLACE VIEW waterway_z10 AS ( - SELECT geometry, 'river'::text AS class, name, name_en, name_de, tags, NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, NULL::boolean AS is_intermittent - FROM osm_important_waterway_linestring_gen2 -); +CREATE OR REPLACE VIEW waterway_z10 AS +( +SELECT geometry, + 'river'::text AS class, + name, + name_en, + name_de, + tags, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_intermittent +FROM osm_important_waterway_linestring_gen2 + ); -- etldoc:osm_important_waterway_linestring_gen1 -> waterway_z11 -CREATE OR REPLACE VIEW waterway_z11 AS ( - SELECT geometry, 'river'::text AS class, name, name_en, name_de, tags, NULL::boolean AS is_bridge, NULL::boolean AS is_tunnel, NULL::boolean AS is_intermittent - FROM osm_important_waterway_linestring_gen1 -); +CREATE OR REPLACE VIEW waterway_z11 AS +( +SELECT geometry, + 'river'::text AS class, + name, + name_en, + name_de, + tags, + NULL::boolean AS is_bridge, + NULL::boolean AS is_tunnel, + NULL::boolean AS is_intermittent +FROM osm_important_waterway_linestring_gen1 + ); -- etldoc: osm_waterway_linestring -> waterway_z12 -CREATE OR REPLACE VIEW waterway_z12 AS ( - SELECT geometry, waterway::text AS class, name, name_en, name_de, tags, is_bridge, is_tunnel, is_intermittent - FROM osm_waterway_linestring - WHERE waterway IN ('river', 'canal') -); +CREATE OR REPLACE VIEW waterway_z12 AS +( +SELECT geometry, + waterway::text AS class, + name, + name_en, + name_de, + tags, + is_bridge, + is_tunnel, + is_intermittent +FROM osm_waterway_linestring +WHERE waterway IN ('river', 'canal') + ); -- etldoc: osm_waterway_linestring -> waterway_z13 -CREATE OR REPLACE VIEW waterway_z13 AS ( - SELECT geometry, waterway::text AS class, name, name_en, name_de, tags, is_bridge, is_tunnel, is_intermittent - FROM osm_waterway_linestring - WHERE waterway IN ('river', 'canal', 'stream', 'drain', 'ditch') -); +CREATE OR REPLACE VIEW waterway_z13 AS +( +SELECT geometry, + waterway::text AS class, + name, + name_en, + name_de, + tags, + is_bridge, + is_tunnel, + is_intermittent +FROM osm_waterway_linestring +WHERE waterway IN ('river', 'canal', 'stream', 'drain', 'ditch') + ); -- etldoc: osm_waterway_linestring -> waterway_z14 -CREATE OR REPLACE VIEW waterway_z14 AS ( - SELECT geometry, waterway::text AS class, name, name_en, name_de, tags, is_bridge, is_tunnel, is_intermittent - FROM osm_waterway_linestring -); +CREATE OR REPLACE VIEW waterway_z14 AS +( +SELECT geometry, + waterway::text AS class, + name, + name_en, + name_de, + tags, + is_bridge, + is_tunnel, + is_intermittent +FROM osm_waterway_linestring + ); -- etldoc: layer_waterway[shape=record fillcolor=lightpink, style="rounded,filled", -- etldoc: label="layer_waterway | z3 | z4-z5 | z6-8 | z9 | z10 | z11 | z12| z13| z14+" ]; CREATE OR REPLACE FUNCTION layer_waterway(bbox geometry, zoom_level int) -RETURNS TABLE(geometry geometry, class text, name text, name_en text, name_de text, brunnel text, intermittent int, tags hstore) AS $$ - SELECT geometry, class, - NULLIF(name, '') AS name, - COALESCE(NULLIF(name_en, ''), name) AS name_en, - COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, - waterway_brunnel(is_bridge, is_tunnel) AS brunnel, - is_intermittent::int AS intermittent, - tags - FROM ( - -- etldoc: waterway_z3 -> layer_waterway:z3 - SELECT * FROM waterway_z3 WHERE zoom_level = 3 - UNION ALL - -- etldoc: waterway_z4 -> layer_waterway:z4_5 - SELECT * FROM waterway_z4 WHERE zoom_level BETWEEN 4 AND 5 - UNION ALL - -- etldoc: waterway_z6 -> layer_waterway:z6_8 - SELECT * FROM waterway_z6 WHERE zoom_level BETWEEN 6 AND 8 - UNION ALL - -- etldoc: waterway_z9 -> layer_waterway:z9 - SELECT * FROM waterway_z9 WHERE zoom_level = 9 - UNION ALL - -- etldoc: waterway_z10 -> layer_waterway:z10 - SELECT * FROM waterway_z10 WHERE zoom_level = 10 - UNION ALL - -- etldoc: waterway_z11 -> layer_waterway:z11 - SELECT * FROM waterway_z11 WHERE zoom_level = 11 - UNION ALL - -- etldoc: waterway_z12 -> layer_waterway:z12 - SELECT * FROM waterway_z12 WHERE zoom_level = 12 - UNION ALL - -- etldoc: waterway_z13 -> layer_waterway:z13 - SELECT * FROM waterway_z13 WHERE zoom_level = 13 - UNION ALL - -- etldoc: waterway_z14 -> layer_waterway:z14 - SELECT * FROM waterway_z14 WHERE zoom_level >= 14 - ) AS zoom_levels - WHERE geometry && bbox; + RETURNS TABLE + ( + geometry geometry, + class text, + name text, + name_en text, + name_de text, + brunnel text, + intermittent int, + tags hstore + ) +AS $$ -LANGUAGE SQL -IMMUTABLE PARALLEL SAFE; +SELECT geometry, + class, + NULLIF(name, '') AS name, + COALESCE(NULLIF(name_en, ''), name) AS name_en, + COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, + waterway_brunnel(is_bridge, is_tunnel) AS brunnel, + is_intermittent::int AS intermittent, + tags +FROM ( + -- etldoc: waterway_z3 -> layer_waterway:z3 + SELECT * + FROM waterway_z3 + WHERE zoom_level = 3 + UNION ALL + -- etldoc: waterway_z4 -> layer_waterway:z4_5 + SELECT * + FROM waterway_z4 + WHERE zoom_level BETWEEN 4 AND 5 + UNION ALL + -- etldoc: waterway_z6 -> layer_waterway:z6_8 + SELECT * + FROM waterway_z6 + WHERE zoom_level BETWEEN 6 AND 8 + UNION ALL + -- etldoc: waterway_z9 -> layer_waterway:z9 + SELECT * + FROM waterway_z9 + WHERE zoom_level = 9 + UNION ALL + -- etldoc: waterway_z10 -> layer_waterway:z10 + SELECT * + FROM waterway_z10 + WHERE zoom_level = 10 + UNION ALL + -- etldoc: waterway_z11 -> layer_waterway:z11 + SELECT * + FROM waterway_z11 + WHERE zoom_level = 11 + UNION ALL + -- etldoc: waterway_z12 -> layer_waterway:z12 + SELECT * + FROM waterway_z12 + WHERE zoom_level = 12 + UNION ALL + -- etldoc: waterway_z13 -> layer_waterway:z13 + SELECT * + FROM waterway_z13 + WHERE zoom_level = 13 + UNION ALL + -- etldoc: waterway_z14 -> layer_waterway:z14 + SELECT * + FROM waterway_z14 + WHERE zoom_level >= 14 + ) AS zoom_levels +WHERE geometry && bbox; +$$ LANGUAGE SQL STABLE + -- STRICT + PARALLEL SAFE; diff --git a/quickstart.sh b/quickstart.sh index d019ea6..6b0e90c 100755 --- a/quickstart.sh +++ b/quickstart.sh @@ -33,7 +33,7 @@ set -o nounset # ./quickstart.sh Adelaide bbbike # .... # -# to list geofabrik areas: make download-geofabrik-list +# to list geofabrik areas: make list-geofabrik or make list-bbbike # see more QUICKSTART.md # @@ -46,32 +46,22 @@ else fi if [ $# -eq 0 ]; then - osm_area=albania # default test country - echo "No parameter - set area=$osm_area " + # default test area + export area=albania + echo "No parameter - set area=$area " else - osm_area=$1 + export area=$1 fi if [ $# -eq 2 ]; then - osm_server=$2 -else - if [[ ${osm_area} == [[:upper:]]* ]]; then - # Only bbbike area names are capitalized - osm_server=bbbike - else - # default OSM server - osm_server=geofabrik - fi + osm_server=$2 fi -pbf_file="./data/${osm_area##*/}-latest.osm.pbf" - ## Min versions ... MIN_COMPOSE_VER=1.7.1 MIN_DOCKER_VER=1.12.3 STARTTIME=$(date +%s) STARTDATE=$(date +"%Y-%m-%dT%H:%M%z") -githash=$( git rev-parse HEAD ) log_file=./quickstart.log rm -f $log_file @@ -118,10 +108,10 @@ echo " Start processing echo "-------------------------------------------------------------------------------------" echo "====> : OpenMapTiles quickstart! [ https://github.com/openmaptiles/openmaptiles ] " echo " : This will be logged to the $log_file file (for debugging) and to the screen" -echo " : Area : $osm_area " -echo " : Download Server : $osm_server " +echo " : Area : $area " +echo " : Download Server : ${osm_server:-unset (automatic)} " echo " : Preloaded Image : $USE_PRELOADED_IMAGE " -echo " : Git version : $githash " +echo " : Git version : $(git rev-parse HEAD) " echo " : Started : $STARTDATE " echo " : Your bash version: $BASH_VERSION" echo " : Your OS : $OSTYPE" @@ -141,7 +131,7 @@ if [[ "$OSTYPE" == "linux-gnu" ]]; then exit 1 fi echo " : --- Memory, CPU info ---- " - mem=$( grep MemTotal /proc/meminfo | awk '{print $2}' | xargs -I {} echo "scale=4; {}/1024^2" | bc ) + mem=$( grep MemTotal /proc/meminfo | awk '{print $2}' | xargs -I {} echo "scale=4; {}/1024^2" | bc ) echo "system memory (GB): ${mem}" grep SwapTotal /proc/meminfo echo "cpu number: $(grep -c processor /proc/cpuinfo) x $(grep "bogomips" /proc/cpuinfo | head -1)" @@ -169,27 +159,13 @@ make init-dirs echo " " echo "-------------------------------------------------------------------------------------" -echo "====> : Removing old MBTILES if exists ( ./data/*.mbtiles ) " -rm -f ./data/*.mbtiles +echo "====> : Removing old MBTILES if exists ( ./data/${area}.mbtiles ) " +rm -f "./data/${area}.mbtiles" -if [[ ! -f "${pbf_file}" || ! -f "./data/docker-compose-config.yml" ]]; then - echo " " - echo "-------------------------------------------------------------------------------------" - echo "====> : Downloading ${osm_area} from ${osm_server}..." - rm -rf ./data/* - make download-${osm_server} "area=${osm_area}" -else - echo " " - echo "-------------------------------------------------------------------------------------" - echo "====> : The pbf file $pbf_file exists, we don't need to download!" -fi - - -if [ ! -f "${pbf_file}" ]; then - echo " " - echo "Missing $pbf_file , Download or Parameter error? " - exit 1 -fi +echo " " +echo "-------------------------------------------------------------------------------------" +echo "====> : Downloading ${area} from ${osm_server:-any source}..." +make "download${osm_server:+-${osm_server}}" echo " " echo "-------------------------------------------------------------------------------------" @@ -244,17 +220,17 @@ fi echo " " echo "-------------------------------------------------------------------------------------" -echo "====> : Start importing OpenStreetMap data: ${pbf_file} -> imposm3[./build/mapping.yaml] -> PostgreSQL" +echo "====> : Start importing OpenStreetMap data: ${area} -> imposm3[./build/mapping.yaml] -> PostgreSQL" echo " : Imposm3 documentation: https://imposm.org/docs/imposm3/latest/index.html " echo " : Thank you Omniscale! " echo " : Source code: https://github.com/openmaptiles/openmaptiles-tools/tree/master/docker/import-osm " echo " : The OpenstreetMap data license: https://www.openstreetmap.org/copyright (ODBL) " echo " : Thank you OpenStreetMap Contributors ! " -make import-osm "PBF_FILE=${pbf_file}" +make import-osm echo " " echo "-------------------------------------------------------------------------------------" -echo "====> : Start importing border data from ${pbf_file} into PostgreSQL using osmborder" +echo "====> : Start importing border ${area} data into PostgreSQL using osmborder" echo " : Source code: https://github.com/pnorman/osmborder" echo " : Data license: http://www.openstreetmap.org/copyright" echo " : Thank you: Paul Norman" @@ -285,11 +261,20 @@ echo "-------------------------------------------------------------------------- echo "====> : Testing PostgreSQL tables to match layer definitions metadata" make test-perf-null +echo " " +echo "-------------------------------------------------------------------------------------" +if [[ "$area" != "planet" ]]; then + echo "====> : Compute bounding box for tile generation" + make generate-dc-config +else + echo "====> : Skipping bbox calculation when generating the entire planet" +fi + echo " " echo "-------------------------------------------------------------------------------------" echo "====> : Start generating MBTiles (containing gzipped MVT PBF) from a TM2Source project. " echo " : TM2Source project definitions : ./build/openmaptiles.tm2source/data.yml " -echo " : Output MBTiles: ./data/tiles.mbtiles " +echo " : Output MBTiles: ./data/${area}.mbtiles " echo " : Source code: https://github.com/openmaptiles/openmaptiles-tools/tree/master/docker/generate-vectortiles " echo " : We are using a lot of Mapbox Open Source tools! : https://github.com/mapbox " echo " : Thank you https://www.mapbox.com !" @@ -304,27 +289,17 @@ echo "-------------------------------------------------------------------------- echo "====> : Stop PostgreSQL service ( but we keep PostgreSQL data volume for debugging )" make stop-db -echo " " -echo "-------------------------------------------------------------------------------------" -echo "====> : Show generated metadata" -make show-metadata - echo " " echo "-------------------------------------------------------------------------------------" echo "====> : Inputs - Outputs md5sum for debugging " rm -f ./data/quickstart_checklist.chk { - find build -type f | sort | xargs md5sum ; - find data -type f | sort | xargs md5sum ; + find build -type f | sort | xargs md5sum + find data -type f | sort | xargs md5sum } >> ./data/quickstart_checklist.chk cat ./data/quickstart_checklist.chk ENDTIME=$(date +%s) -if stat --help >/dev/null 2>&1; then - MODDATE=$(stat -c %y "${pbf_file}" ) -else - MODDATE=$(stat -f%Sm -t '%F %T %z' "${pbf_file}" ) -fi echo " " echo " " @@ -339,15 +314,14 @@ docker images | grep openmaptiles echo " " echo "-------------------------------------------------------------------------------------" -echo "====> : (disk space) We have created the new vectortiles ( ./data/tiles.mbtiles ) " +echo "====> : (disk space) We have created the new vectortiles ( ./data/${area}.mbtiles ) " echo " : Please respect the licenses (OdBL for OSM data) of the sources when distributing the MBTiles file." -echo " : Created from $pbf_file ( file moddate: $MODDATE ) " -echo " : Size: " -ls -la ./data/*.mbtiles +echo " : Data directory content:" +ls -la ./data echo " " echo "-------------------------------------------------------------------------------------" -echo "The ./quickstart.sh $osm_area is finished! " +echo "The ./quickstart.sh $area is finished! " echo "It takes $((ENDTIME - STARTTIME)) seconds to complete" echo "We saved the log file to $log_file ( for debugging ) You can compare with the travis log !" echo " "