Manage field mapping in SQL declaratively

Simplify some of the OSM->OMT field value mappings using declarative syntax.

This approach is not for all cases, but in many it removes
the need of storing the same field in both the .yaml and .sql files.

TODO: support more complex AND/OR cases
pull/693/head
Yuri Astrakhan 2019-10-26 04:28:51 -04:00
rodzic f3667170f6
commit 1614a4656c
10 zmienionych plików z 156 dodań i 120 usunięć

Wyświetl plik

@ -15,12 +15,23 @@ layer:
[`aerodrome`](http://wiki.openstreetmap.org/wiki/Proposed_features/Aerodrome) [`aerodrome`](http://wiki.openstreetmap.org/wiki/Proposed_features/Aerodrome)
and `aerodrome:type` tags. and `aerodrome:type` tags.
values: values:
- international international:
- public aerodrome: 'international'
- regional aerodrome_type: 'international'
- military public:
- private aerodrome: 'public'
- other aerodrome_type: ['%public%', 'civil']
regional:
aerodrome: 'regional'
aerodrome_type: 'regional'
military:
aerodrome: 'military'
aerodrome_type: '%military%'
military: 'airfield'
private:
aerodrome: 'private'
aerodrome_type: 'private'
other:
iata: 3-character code issued by the IATA. iata: 3-character code issued by the IATA.
icao: 4-letter code issued by the ICAO. icao: 4-letter code issued by the ICAO.
ele: Elevation (`ele`) in meters. ele: Elevation (`ele`) in meters.

Wyświetl plik

@ -27,27 +27,7 @@ $$
COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de, COALESCE(NULLIF(name_de, ''), name, name_en) AS name_de,
tags, tags,
CASE CASE
WHEN aerodrome = 'international' %%FIELD_MAPPING: class %%
OR aerodrome_type = 'international'
THEN 'international'
WHEN
aerodrome = 'public'
OR aerodrome_type LIKE '%public%'
OR aerodrome_type = 'civil'
THEN 'public'
WHEN
aerodrome = 'regional'
OR aerodrome_type = 'regional'
THEN 'regional'
WHEN
aerodrome = 'military'
OR aerodrome_type LIKE '%military%'
OR military = 'airfield'
THEN 'military'
WHEN
aerodrome = 'private'
OR aerodrome_type = 'private'
THEN 'private'
ELSE 'other' ELSE 'other'
END AS class, END AS class,
NULLIF(iata, '') AS iata, NULLIF(iata, '') AS iata,

Wyświetl plik

@ -11,15 +11,7 @@
CREATE OR REPLACE FUNCTION landcover_class(subclass VARCHAR) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION landcover_class(subclass VARCHAR) RETURNS TEXT AS $$
SELECT CASE SELECT CASE
WHEN subclass IN ('farmland', 'farm', 'orchard', 'vineyard', 'plant_nursery') THEN 'farmland' %%FIELD_MAPPING: class %%
WHEN subclass IN ('glacier', 'ice_shelf') THEN 'ice'
WHEN subclass IN ('wood', 'forest') THEN 'wood'
WHEN subclass IN ('bare_rock', 'scree') THEN 'rock'
WHEN subclass IN ('fell', 'grassland', 'heath', 'scrub', 'tundra', 'grass', 'meadow', 'allotments',
'park', 'village_green', 'recreation_ground', 'garden', 'golf_course') THEN 'grass'
WHEN subclass IN ('wetland', 'bog', 'swamp', 'wet_meadow', 'marsh', 'reedbed',
'saltern', 'tidalflat', 'saltmarsh', 'mangrove') THEN 'wetland'
WHEN subclass IN ('beach', 'sand', 'dune') THEN 'sand'
ELSE NULL ELSE NULL
END; END;
$$ LANGUAGE SQL IMMUTABLE; $$ LANGUAGE SQL IMMUTABLE;

Wyświetl plik

@ -10,12 +10,20 @@ layer:
description: | description: |
Use the **class** to assign natural colors for **landcover**. Use the **class** to assign natural colors for **landcover**.
values: values:
- farmland farmland:
- ice subclass: ['farmland', 'farm', 'orchard', 'vineyard', 'plant_nursery']
- wood ice:
- grass subclass: ['glacier', 'ice_shelf']
- wetland wood:
- sand subclass: ['wood', 'forest']
rock:
subclass: ['bare_rock', 'scree']
grass:
subclass: ['fell', 'grassland', 'heath', 'scrub', 'tundra', 'grass', 'meadow', 'allotments', 'park', 'village_green', 'recreation_ground', 'garden', 'golf_course']
wetland:
subclass: ['wetland', 'bog', 'swamp', 'wet_meadow', 'marsh', 'reedbed', 'saltern', 'tidalflat', 'saltmarsh', 'mangrove']
sand:
subclass: ['beach', 'sand', 'dune']
subclass: subclass:
description: | description: |
Use **subclass** to do more precise styling. Use **subclass** to do more precise styling.

Wyświetl plik

@ -30,39 +30,10 @@ $$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION poi_class(subclass TEXT, mapping_key TEXT) CREATE OR REPLACE FUNCTION poi_class(subclass TEXT, mapping_key TEXT)
RETURNS TEXT AS $$ RETURNS TEXT AS $$
SELECT CASE SELECT CASE
WHEN subclass IN ('accessories','antiques','beauty','bed','boutique','camera','carpet','charity','chemist','coffee','computer','convenience','copyshop','cosmetics','garden_centre','doityourself','erotic','electronics','fabric','florist','frozen_food','furniture','video_games','video','general','gift','hardware','hearing_aids','hifi','ice_cream','interior_decoration','jewelry','kiosk','lamps','mall','massage','motorcycle','mobile_phone','newsagent','optician','outdoor','perfumery','perfume','pet','photo','second_hand','shoes','sports','stationery','tailor','tattoo','ticket','tobacco','toys','travel_agency','watches','weapons','wholesale') THEN 'shop' %%FIELD_MAPPING: class %%
WHEN subclass IN ('townhall','public_building','courthouse','community_centre') THEN 'town_hall' WHEN (subclass = 'station' AND mapping_key = 'railway')
WHEN subclass IN ('golf','golf_course','miniature_golf') THEN 'golf' OR (subclass IN ('halt', 'tram_stop', 'subway')) THEN 'railway'
WHEN subclass IN ('fast_food','food_court') THEN 'fast_food' WHEN (subclass = 'station' AND mapping_key = 'aerialway') THEN 'aerialway'
WHEN subclass IN ('park','bbq') THEN 'park'
WHEN subclass IN ('bus_stop','bus_station') THEN 'bus'
WHEN (subclass='station' AND mapping_key = 'railway') OR subclass IN ('halt', 'tram_stop', 'subway') THEN 'railway'
WHEN (subclass='station' AND mapping_key = 'aerialway') THEN 'aerialway'
WHEN subclass IN ('subway_entrance','train_station_entrance') THEN 'entrance'
WHEN subclass IN ('camp_site','caravan_site') THEN 'campsite'
WHEN subclass IN ('laundry','dry_cleaning') THEN 'laundry'
WHEN subclass IN ('supermarket','deli','delicatessen','department_store','greengrocer','marketplace') THEN 'grocery'
WHEN subclass IN ('books','library') THEN 'library'
WHEN subclass IN ('university','college') THEN 'college'
WHEN subclass IN ('hotel','motel','bed_and_breakfast','guest_house','hostel','chalet','alpine_hut','dormitory') THEN 'lodging'
WHEN subclass IN ('chocolate','confectionery') THEN 'ice_cream'
WHEN subclass IN ('post_box','post_office') THEN 'post'
WHEN subclass IN ('cafe') THEN 'cafe'
WHEN subclass IN ('school','kindergarten') THEN 'school'
WHEN subclass IN ('alcohol','beverages','wine') THEN 'alcohol_shop'
WHEN subclass IN ('bar','nightclub') THEN 'bar'
WHEN subclass IN ('marina','dock') THEN 'harbor'
WHEN subclass IN ('car','car_repair','taxi') THEN 'car'
WHEN subclass IN ('hospital','nursing_home', 'clinic') THEN 'hospital'
WHEN subclass IN ('grave_yard','cemetery') THEN 'cemetery'
WHEN subclass IN ('attraction','viewpoint') THEN 'attraction'
WHEN subclass IN ('biergarten','pub') THEN 'beer'
WHEN subclass IN ('music','musical_instrument') THEN 'music'
WHEN subclass IN ('american_football','stadium','soccer') THEN 'stadium'
WHEN subclass IN ('art','artwork','gallery','arts_centre') THEN 'art_gallery'
WHEN subclass IN ('bag','clothes') THEN 'clothing_store'
WHEN subclass IN ('swimming_area','swimming') THEN 'swimming'
WHEN subclass IN ('castle','ruins') THEN 'castle'
ELSE subclass ELSE subclass
END; END;
$$ LANGUAGE SQL IMMUTABLE; $$ LANGUAGE SQL IMMUTABLE;

Wyświetl plik

@ -9,11 +9,84 @@ layer:
name: The OSM [`name`](http://wiki.openstreetmap.org/wiki/Key:name) value of the POI. name: The OSM [`name`](http://wiki.openstreetmap.org/wiki/Key:name) value of the POI.
name_en: English name `name:en` if available, otherwise `name`. name_en: English name `name:en` if available, otherwise `name`.
name_de: German name `name:de` if available, otherwise `name` or `name:en`. name_de: German name `name:de` if available, otherwise `name` or `name:en`.
class: | class:
description: |
More general classes of POIs. If there is no more general `class` for the `subclass` More general classes of POIs. If there is no more general `class` for the `subclass`
this field will contain the same value as `subclass`. this field will contain the same value as `subclass`.
But for example for schools you only need to style the class `school` to filter the subclasses `school` But for example for schools you only need to style the class `school` to filter the subclasses `school`
and `kindergarten`. Or use the class `shop` to style all shops. and `kindergarten`. Or use the class `shop` to style all shops.
values:
shop:
subclass: ['accessories', 'antiques', 'beauty', 'bed', 'boutique', 'camera', 'carpet', 'charity', 'chemist',
'coffee', 'computer', 'convenience', 'copyshop', 'cosmetics', 'garden_centre', 'doityourself',
'erotic', 'electronics', 'fabric', 'florist', 'frozen_food', 'furniture', 'video_games', 'video',
'general', 'gift', 'hardware', 'hearing_aids', 'hifi', 'ice_cream', 'interior_decoration',
'jewelry', 'kiosk', 'lamps', 'mall', 'massage', 'motorcycle', 'mobile_phone', 'newsagent',
'optician', 'outdoor', 'perfumery', 'perfume', 'pet', 'photo', 'second_hand', 'shoes', 'sports',
'stationery', 'tailor', 'tattoo', 'ticket', 'tobacco', 'toys', 'travel_agency', 'watches',
'weapons', 'wholesale']
town_hall:
subclass: ['townhall', 'public_building', 'courthouse', 'community_centre']
golf:
subclass: ['golf', 'golf_course', 'miniature_golf']
fast_food:
subclass: ['fast_food', 'food_court']
park:
subclass: ['park', 'bbq']
bus:
subclass: ['bus_stop', 'bus_station']
railway:
aerialway:
entrance:
subclass: ['subway_entrance', 'train_station_entrance']
campsite:
subclass: ['camp_site', 'caravan_site']
laundry:
subclass: ['laundry', 'dry_cleaning']
grocery:
subclass: ['supermarket', 'deli', 'delicatessen', 'department_store', 'greengrocer', 'marketplace']
library:
subclass: ['books', 'library']
college:
subclass: ['university', 'college']
lodging:
subclass: ['hotel', 'motel', 'bed_and_breakfast', 'guest_house', 'hostel', 'chalet', 'alpine_hut', 'dormitory']
ice_cream:
subclass: ['chocolate', 'confectionery']
post:
subclass: ['post_box', 'post_office']
cafe:
subclass: ['cafe']
school:
subclass: ['school', 'kindergarten']
alcohol_shop:
subclass: ['alcohol', 'beverages', 'wine']
bar:
subclass: ['bar', 'nightclub']
harbor:
subclass: ['marina', 'dock']
car:
subclass: ['car', 'car_repair', 'taxi']
hospital:
subclass: ['hospital', 'nursing_home', 'clinic']
cemetery:
subclass: ['grave_yard', 'cemetery']
attraction:
subclass: ['attraction', 'viewpoint']
beer:
subclass: ['biergarten', 'pub']
music:
subclass: ['music', 'musical_instrument']
stadium:
subclass: ['american_football', 'stadium', 'soccer']
art_gallery:
subclass: ['art', 'artwork', 'gallery', 'arts_centre']
clothing_store:
subclass: ['bag', 'clothes']
swimming:
subclass: ['swimming_area', 'swimming']
castle:
subclass: ['castle', 'ruins']
subclass: subclass:
description: | description: |
Original value of either the Original value of either the

Wyświetl plik

@ -11,23 +11,19 @@ $$ LANGUAGE SQL IMMUTABLE STRICT;
-- https://github.com/ClearTables/ClearTables/blob/master/transportation.lua -- 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 $$ CREATE OR REPLACE FUNCTION highway_class(highway TEXT, public_transport TEXT, construction TEXT) RETURNS TEXT AS $$
SELECT CASE SELECT CASE
WHEN highway IN ('motorway', 'motorway_link') THEN 'motorway' %%FIELD_MAPPING: class %%
WHEN highway IN ('trunk', 'trunk_link') THEN 'trunk'
WHEN highway IN ('primary', 'primary_link') THEN 'primary'
WHEN highway IN ('secondary', 'secondary_link') THEN 'secondary'
WHEN highway IN ('tertiary', 'tertiary_link') THEN 'tertiary'
WHEN highway IN ('unclassified', 'residential', 'living_street', 'road') THEN 'minor'
WHEN highway IN ('pedestrian', 'path', 'footway', 'cycleway', 'steps', 'bridleway', 'corridor') OR public_transport IN ('platform') THEN 'path'
WHEN highway IN ('service', 'track', 'raceway') THEN highway
WHEN highway = 'construction' THEN CASE WHEN highway = 'construction' THEN CASE
WHEN construction IN ('motorway', 'motorway_link') THEN 'motorway_construction' WHEN construction IN ('motorway', 'motorway_link') THEN 'motorway_construction'
WHEN construction IN ('trunk', 'trunk_link') THEN 'trunk_construction' WHEN construction IN ('trunk', 'trunk_link') THEN 'trunk_construction'
WHEN construction IN ('primary', 'primary_link') THEN 'primary_construction' WHEN construction IN ('primary', 'primary_link') THEN 'primary_construction'
WHEN construction IN ('secondary', 'secondary_link') THEN 'secondary_construction' WHEN construction IN ('secondary', 'secondary_link') THEN 'secondary_construction'
WHEN construction IN ('tertiary', 'tertiary_link') THEN 'tertiary_construction' WHEN construction IN ('tertiary', 'tertiary_link') THEN 'tertiary_construction'
WHEN construction = '' OR construction IN ('unclassified', 'residential', 'living_street', 'road') THEN 'minor_construction' WHEN construction IN ('', 'unclassified', 'residential', 'living_street', 'road') THEN 'minor_construction'
WHEN construction IN ('pedestrian', 'path', 'footway', 'cycleway', 'steps', 'bridleway', 'corridor') OR public_transport IN ('platform') THEN 'path_construction' WHEN construction IN ('pedestrian', 'path', 'footway', 'cycleway', 'steps', 'bridleway', 'corridor')
WHEN construction IN ('service', 'track', 'raceway') THEN CONCAT(highway, '_construction') OR public_transport = 'platform' THEN 'path_construction'
WHEN construction = 'service' THEN 'service_construction'
WHEN construction = 'track' THEN 'track_construction'
WHEN construction = 'raceway' THEN 'raceway_construction'
ELSE NULL ELSE NULL
END END
ELSE NULL ELSE NULL

Wyświetl plik

@ -24,33 +24,37 @@ layer:
shipping ways), or shipping ways), or
[`man_made`](http://wiki.openstreetmap.org/wiki/Key:route). [`man_made`](http://wiki.openstreetmap.org/wiki/Key:route).
values: values:
- motorway motorway:
- trunk highway: ['motorway', 'motorway_link']
- primary trunk:
- secondary highway: ['trunk', 'trunk_link']
- tertiary primary:
- minor highway: ['primary', 'primary_link']
- service secondary:
- track highway: ['secondary', 'secondary_link']
- path tertiary:
- raceway highway: ['tertiary', 'tertiary_link']
- motorway_construction minor:
- trunk_construction highway: ['unclassified', 'residential', 'living_street', 'road']
- primary_construction path:
- secondary_construction highway: ['pedestrian', 'path', 'footway', 'cycleway', 'steps', 'bridleway', 'corridor']
- tertiary_construction public_transport: 'platform'
- minor_construction service:
- service_construction highway: service
- track_construction track:
- path_construction highway: track
- raceway_construction raceway:
- rail highway: raceway
- transit motorway_construction:
- cable_car trunk_construction:
- gondola primary_construction:
- ferry secondary_construction:
- bridge tertiary_construction:
- pier minor_construction:
path_construction:
service_construction:
track_construction:
raceway_construction:
subclass: subclass:
description: | description: |
Distinguish more specific classes of railway and path: Distinguish more specific classes of railway and path:

Wyświetl plik

@ -1,8 +1,6 @@
CREATE OR REPLACE FUNCTION water_class(waterway TEXT) RETURNS TEXT AS $$ CREATE OR REPLACE FUNCTION water_class(waterway TEXT) RETURNS TEXT AS $$
SELECT CASE SELECT CASE
WHEN waterway='' THEN 'lake' %%FIELD_MAPPING: class %%
WHEN waterway='lake' THEN 'lake'
WHEN waterway='dock' THEN 'dock'
ELSE 'river' ELSE 'river'
END; END;
$$ LANGUAGE SQL IMMUTABLE; $$ LANGUAGE SQL IMMUTABLE;

Wyświetl plik

@ -14,9 +14,12 @@ layer:
All water polygons from [OpenStreetMapData](http://osmdata.openstreetmap.de/) have the class `ocean`. All water polygons from [OpenStreetMapData](http://osmdata.openstreetmap.de/) have the class `ocean`.
Water bodies are classified as `lake` or `river` for water bodies with the [`waterway`](http://wiki.openstreetmap.org/wiki/Key:waterway) tag. Water bodies are classified as `lake` or `river` for water bodies with the [`waterway`](http://wiki.openstreetmap.org/wiki/Key:waterway) tag.
values: values:
- ocean lake:
- lake waterway: ['', 'lake']
- river dock:
waterway: 'dock'
river:
ocean:
intermittent: intermittent:
description: | description: |
Mark with `1` if it is an [intermittent](http://wiki.openstreetmap.org/wiki/Key:intermittent) water polygon. Mark with `1` if it is an [intermittent](http://wiki.openstreetmap.org/wiki/Key:intermittent) water polygon.