mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 05:18:00 +00:00
reorganise place_insert trigger
Code cleanup and formatting as well as minor improvements, in particular removal of unnecessary code.
This commit is contained in:
@@ -10,300 +10,323 @@ CREATE OR REPLACE FUNCTION place_insert()
|
||||
AS $$
|
||||
DECLARE
|
||||
i INTEGER;
|
||||
country RECORD;
|
||||
existing RECORD;
|
||||
existingplacex RECORD;
|
||||
existingline RECORD;
|
||||
existinggeometry GEOMETRY;
|
||||
existingplace_id BIGINT;
|
||||
result BOOLEAN;
|
||||
partition INTEGER;
|
||||
BEGIN
|
||||
|
||||
{% if debug %}
|
||||
RAISE WARNING '-----------------------------------------------------------------------------------';
|
||||
RAISE WARNING 'place_insert: % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,st_area(NEW.geometry);
|
||||
{% endif %}
|
||||
-- filter wrong tupels
|
||||
IF ST_IsEmpty(NEW.geometry) OR NOT ST_IsValid(NEW.geometry) OR ST_X(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') OR ST_Y(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') THEN
|
||||
INSERT INTO import_polygon_error (osm_type, osm_id, class, type, name, country_code, updated, errormessage, prevgeometry, newgeometry)
|
||||
VALUES (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name, NEW.address->'country', now(), ST_IsValidReason(NEW.geometry), null, NEW.geometry);
|
||||
-- RAISE WARNING 'Invalid Geometry: % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type;
|
||||
|
||||
-- Filter tuples with bad geometries.
|
||||
IF ST_IsEmpty(NEW.geometry) OR NOT ST_IsValid(NEW.geometry) THEN
|
||||
INSERT INTO import_polygon_error (osm_type, osm_id, class, type, name,
|
||||
country_code, updated, errormessage,
|
||||
prevgeometry, newgeometry)
|
||||
VALUES (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name,
|
||||
NEW.address->'country', now(), ST_IsValidReason(NEW.geometry),
|
||||
null, NEW.geometry);
|
||||
{% if debug %}
|
||||
RAISE WARNING 'Invalid Geometry: % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type;
|
||||
{% endif %}
|
||||
RETURN null;
|
||||
END IF;
|
||||
|
||||
-- decide, whether it is an osm interpolation line => insert intoosmline, or else just placex
|
||||
IF NEW.class='place' and NEW.type='houses' and NEW.osm_type='W' and ST_GeometryType(NEW.geometry) = 'ST_LineString' THEN
|
||||
-- Have we already done this place?
|
||||
select * from place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type INTO existing;
|
||||
-- Have we already done this place?
|
||||
SELECT * INTO existing
|
||||
FROM place
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
|
||||
-- Get the existing place_id
|
||||
select * from location_property_osmline where osm_id = NEW.osm_id INTO existingline;
|
||||
{% if debug %}RAISE WARNING 'Existing: %',existing.osm_id;{% endif %}
|
||||
|
||||
-- Handle a place changing type by removing the old data (this trigger is executed BEFORE INSERT of the NEW tupel)
|
||||
IF existing.osm_type IS NULL THEN
|
||||
DELETE FROM place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class;
|
||||
END IF;
|
||||
-- Handle a place changing type by removing the old data.
|
||||
-- (This trigger is executed BEFORE INSERT of the NEW tuple.)
|
||||
IF existing.osm_type IS NULL THEN
|
||||
DELETE FROM place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class;
|
||||
END IF;
|
||||
|
||||
DELETE from import_polygon_error where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
DELETE from import_polygon_delete where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
-- Remove any old logged data.
|
||||
DELETE from import_polygon_error where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
DELETE from import_polygon_delete where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
|
||||
-- update method for interpolation lines: delete all old interpolation lines with same osm_id (update on place) and insert the new one(s) (they can be split up, if they have > 2 nodes)
|
||||
-- ---- Interpolation Lines
|
||||
|
||||
IF NEW.class='place' and NEW.type='houses'
|
||||
and NEW.osm_type='W' and ST_GeometryType(NEW.geometry) = 'ST_LineString'
|
||||
THEN
|
||||
-- Get the existing entry from the interpolation table.
|
||||
SELECT * INTO existingline
|
||||
FROM location_property_osmline WHERE osm_id = NEW.osm_id;
|
||||
|
||||
-- Update the interpolation table:
|
||||
-- delete all old interpolation lines with same osm_id
|
||||
-- and insert the new one(s) (they can be split up, if they have > 2 nodes)
|
||||
IF existingline.osm_id IS NOT NULL THEN
|
||||
delete from location_property_osmline where osm_id = NEW.osm_id;
|
||||
DELETE FROM location_property_osmline where osm_id = NEW.osm_id;
|
||||
END IF;
|
||||
|
||||
-- for interpolations invalidate all nodes on the line
|
||||
update placex p set indexed_status = 2
|
||||
from planet_osm_ways w
|
||||
where w.id = NEW.osm_id and p.osm_type = 'N' and p.osm_id = any(w.nodes);
|
||||
|
||||
|
||||
INSERT INTO location_property_osmline (osm_id, address, linegeo)
|
||||
VALUES (NEW.osm_id, NEW.address, NEW.geometry);
|
||||
|
||||
-- Now invalidate all address nodes on the line.
|
||||
-- They get their parent from the interpolation.
|
||||
UPDATE placex p SET indexed_status = 2
|
||||
FROM planet_osm_ways w
|
||||
WHERE w.id = NEW.osm_id and p.osm_type = 'N' and p.osm_id = any(w.nodes);
|
||||
|
||||
IF existing.osm_type IS NULL THEN
|
||||
return NEW;
|
||||
-- If there is already an entry in place, just update that, if necessary.
|
||||
IF existing.osm_type is not null THEN
|
||||
IF coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
OR existing.geometry::text != NEW.geometry::text
|
||||
THEN
|
||||
UPDATE place
|
||||
SET name = NEW.name,
|
||||
address = NEW.address,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
geometry = NEW.geometry
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
END IF;
|
||||
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
IF coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
OR (coalesce(existing.extratags, ''::hstore) != coalesce(NEW.extratags, ''::hstore))
|
||||
OR existing.geometry::text != NEW.geometry::text
|
||||
THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
update place set
|
||||
name = NEW.name,
|
||||
address = NEW.address,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
geometry = NEW.geometry
|
||||
where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
|
||||
END IF;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
ELSE -- insert to placex
|
||||
|
||||
-- Patch in additional country names
|
||||
IF NEW.admin_level = 2 AND NEW.type = 'administrative'
|
||||
AND NEW.address is not NULL AND NEW.address ? 'country' THEN
|
||||
SELECT name FROM country_name WHERE country_code = lower(NEW.address->'country') INTO existing;
|
||||
IF existing.name IS NOT NULL THEN
|
||||
NEW.name = existing.name || NEW.name;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- Have we already done this place?
|
||||
select * from place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type INTO existing;
|
||||
|
||||
-- Get the existing place_id
|
||||
select * from placex where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type INTO existingplacex;
|
||||
|
||||
-- Handle a place changing type by removing the old data
|
||||
-- My generated 'place' types are causing havok because they overlap with real keys
|
||||
-- TODO: move them to their own special purpose key/class to avoid collisions
|
||||
IF existing.osm_type IS NULL THEN
|
||||
DELETE FROM place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class;
|
||||
END IF;
|
||||
-- ---- Postcode points.
|
||||
|
||||
IF NEW.class = 'place' AND NEW.type = 'postcode' THEN
|
||||
-- Pure postcodes are never queried from placex so we don't add them.
|
||||
-- location_postcodes is filled from the place table directly.
|
||||
IF NEW.class = 'place' AND NEW.type = 'postcode' THEN
|
||||
-- Remove old placex entry.
|
||||
DELETE FROM placex where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
|
||||
IF existing.osm_type IS NOT NULL THEN
|
||||
IF coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
OR existing.geometry::text != NEW.geometry::text
|
||||
THEN
|
||||
-- Remove any old placex entry.
|
||||
DELETE FROM placex WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
|
||||
update place set address = NEW.address, geometry = NEW.geometry
|
||||
where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
|
||||
END IF;
|
||||
IF existing.osm_type IS NOT NULL THEN
|
||||
IF coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
OR existing.geometry::text != NEW.geometry::text
|
||||
THEN
|
||||
UPDATE place
|
||||
SET name = NEW.name,
|
||||
address = NEW.address,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
geometry = NEW.geometry
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
END IF;
|
||||
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
-- ---- All other place types.
|
||||
|
||||
-- Patch in additional country names
|
||||
IF NEW.admin_level = 2 and NEW.type = 'administrative' and NEW.address ? 'country'
|
||||
THEN
|
||||
FOR country IN
|
||||
SELECT name FROM country_name WHERE country_code = lower(NEW.address->'country')
|
||||
LOOP
|
||||
NEW.name = country.name || NEW.name;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
-- When an area is changed from large to small: log and discard change
|
||||
IF existing.geometry is not null AND ST_IsValid(existing.geometry)
|
||||
AND ST_Area(existing.geometry) > 0.02
|
||||
AND ST_GeometryType(NEW.geometry) in ('ST_Polygon','ST_MultiPolygon')
|
||||
AND ST_Area(NEW.geometry) < ST_Area(existing.geometry) * 0.5
|
||||
THEN
|
||||
INSERT INTO import_polygon_error (osm_type, osm_id, class, type, name,
|
||||
country_code, updated, errormessage,
|
||||
prevgeometry, newgeometry)
|
||||
VALUES (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name,
|
||||
NEW.address->'country', now(),
|
||||
'Area reduced from '||st_area(existing.geometry)||' to '||st_area(NEW.geometry),
|
||||
existing.geometry, NEW.geometry);
|
||||
|
||||
RETURN null;
|
||||
END IF;
|
||||
|
||||
-- Get the existing placex entry.
|
||||
SELECT * INTO existingplacex
|
||||
FROM placex
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
|
||||
{% if debug %}RAISE WARNING 'Existing PlaceX: %',existingplacex.place_id;{% endif %}
|
||||
|
||||
-- To paraphrase: if there isn't an existing item, OR if the admin level has changed
|
||||
IF existingplacex.osm_type IS NULL
|
||||
or (existingplacex.class = 'boundary'
|
||||
and ((coalesce(existingplacex.admin_level, 15) != coalesce(NEW.admin_level, 15)
|
||||
and existingplacex.type = 'administrative')
|
||||
or existingplacex.type != NEW.type))
|
||||
THEN
|
||||
{% if config.get_bool('LIMIT_REINDEXING') %}
|
||||
-- sanity check: ignore admin_level changes on places with too many active children
|
||||
-- or we end up reindexing entire countries because somebody accidentally deleted admin_level
|
||||
IF existingplacex.osm_type IS NOT NULL THEN
|
||||
SELECT count(*) INTO i FROM
|
||||
(SELECT 'a' FROM placex, place_addressline
|
||||
WHERE address_place_id = existingplacex.place_id
|
||||
and placex.place_id = place_addressline.place_id
|
||||
and indexed_status = 0 and place_addressline.isaddress LIMIT 100001) sub;
|
||||
IF i > 100000 THEN
|
||||
RETURN null;
|
||||
END IF;
|
||||
END IF;
|
||||
{% endif %}
|
||||
|
||||
IF existing.osm_type IS NOT NULL THEN
|
||||
-- Pathological case caused by the triggerless copy into place during initial import
|
||||
-- force delete even for large areas, it will be reinserted later
|
||||
UPDATE place SET geometry = ST_SetSRID(ST_Point(0,0), 4326)
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
DELETE FROM place
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
END IF;
|
||||
|
||||
-- Process it as a new insertion
|
||||
INSERT INTO placex (osm_type, osm_id, class, type, name,
|
||||
admin_level, address, extratags, geometry)
|
||||
VALUES (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name,
|
||||
NEW.admin_level, NEW.address, NEW.extratags, NEW.geometry);
|
||||
|
||||
{% if debug %}RAISE WARNING 'insert done % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,NEW.name;{% endif %}
|
||||
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
-- Special case for polygon shape changes because they tend to be large
|
||||
-- and we can be a bit clever about how we handle them
|
||||
IF existing.geometry::text != NEW.geometry::text
|
||||
AND ST_GeometryType(existing.geometry) in ('ST_Polygon','ST_MultiPolygon')
|
||||
AND ST_GeometryType(NEW.geometry) in ('ST_Polygon','ST_MultiPolygon')
|
||||
THEN
|
||||
-- Performance limit
|
||||
IF ST_Area(NEW.geometry) < 0.000000001 AND ST_Area(existingplacex.geometry) < 1
|
||||
THEN
|
||||
-- re-index points that have moved in / out of the polygon.
|
||||
-- Could be done as a single query but postgres gets the index usage wrong.
|
||||
update placex set indexed_status = 2 where indexed_status = 0
|
||||
AND ST_Intersects(NEW.geometry, placex.geometry)
|
||||
AND NOT ST_Intersects(existingplacex.geometry, placex.geometry)
|
||||
AND rank_search > existingplacex.rank_search AND (rank_search < 28 or name is not null);
|
||||
|
||||
update placex set indexed_status = 2 where indexed_status = 0
|
||||
AND ST_Intersects(existingplacex.geometry, placex.geometry)
|
||||
AND NOT ST_Intersects(NEW.geometry, placex.geometry)
|
||||
AND rank_search > existingplacex.rank_search AND (rank_search < 28 or name is not null);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
|
||||
-- Has something relevant changed?
|
||||
IF coalesce(existing.name::text, '') != coalesce(NEW.name::text, '')
|
||||
OR coalesce(existing.extratags::text, '') != coalesce(NEW.extratags::text, '')
|
||||
OR coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
OR coalesce(existing.admin_level, 15) != coalesce(NEW.admin_level, 15)
|
||||
OR existing.geometry::text != NEW.geometry::text
|
||||
THEN
|
||||
UPDATE place
|
||||
SET name = NEW.name,
|
||||
address = NEW.address,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
geometry = NEW.geometry
|
||||
WHERE osm_type = NEW.osm_type and osm_id = NEW.osm_id
|
||||
and class = NEW.class and type = NEW.type;
|
||||
|
||||
-- Postcode areas are only kept, when there is an actual postcode assigned.
|
||||
IF NEW.class = 'boundary' AND NEW.type = 'postal_code' THEN
|
||||
IF NEW.address is NULL OR NOT NEW.address ? 'postcode' THEN
|
||||
-- postcode was deleted, no longer retain in placex
|
||||
DELETE FROM placex where place_id = existingplacex.place_id;
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
NEW.name := hstore('ref', NEW.address->'postcode');
|
||||
END IF;
|
||||
|
||||
{% if debug %}RAISE WARNING 'Existing: %',existing.osm_id;{% endif %}
|
||||
{% if debug %}RAISE WARNING 'Existing PlaceX: %',existingplacex.place_id;{% endif %}
|
||||
|
||||
-- Log and discard
|
||||
IF existing.geometry is not null AND st_isvalid(existing.geometry)
|
||||
AND st_area(existing.geometry) > 0.02
|
||||
AND ST_GeometryType(NEW.geometry) in ('ST_Polygon','ST_MultiPolygon')
|
||||
AND st_area(NEW.geometry) < st_area(existing.geometry)*0.5
|
||||
THEN
|
||||
INSERT INTO import_polygon_error (osm_type, osm_id, class, type, name, country_code, updated, errormessage, prevgeometry, newgeometry)
|
||||
VALUES (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name, NEW.address->'country', now(),
|
||||
'Area reduced from '||st_area(existing.geometry)||' to '||st_area(NEW.geometry), existing.geometry, NEW.geometry);
|
||||
RETURN null;
|
||||
END IF;
|
||||
|
||||
DELETE from import_polygon_error where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
DELETE from import_polygon_delete where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
|
||||
|
||||
-- To paraphrase, if there isn't an existing item, OR if the admin level has changed
|
||||
IF existingplacex.osm_type IS NULL OR
|
||||
(existingplacex.class = 'boundary' AND
|
||||
((coalesce(existingplacex.admin_level, 15) != coalesce(NEW.admin_level, 15) AND existingplacex.type = 'administrative') OR
|
||||
(existingplacex.type != NEW.type)))
|
||||
-- Boundaries must be areas.
|
||||
IF NEW.class in ('boundary')
|
||||
AND ST_GeometryType(NEW.geometry) not in ('ST_Polygon','ST_MultiPolygon')
|
||||
THEN
|
||||
|
||||
{% if config.get_bool('LIMIT_REINDEXING') %}
|
||||
IF existingplacex.osm_type IS NOT NULL THEN
|
||||
-- sanity check: ignore admin_level changes on places with too many active children
|
||||
-- or we end up reindexing entire countries because somebody accidentally deleted admin_level
|
||||
SELECT count(*) INTO i FROM
|
||||
(SELECT 'a' FROM placex, place_addressline
|
||||
WHERE address_place_id = existingplacex.place_id
|
||||
and placex.place_id = place_addressline.place_id
|
||||
and indexed_status = 0 and place_addressline.isaddress LIMIT 100001) sub;
|
||||
IF i > 100000 THEN
|
||||
RETURN null;
|
||||
END IF;
|
||||
END IF;
|
||||
{% endif %}
|
||||
|
||||
IF existing.osm_type IS NOT NULL THEN
|
||||
-- pathological case caused by the triggerless copy into place during initial import
|
||||
-- force delete even for large areas, it will be reinserted later
|
||||
UPDATE place set geometry = ST_SetSRID(ST_Point(0,0), 4326) where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
|
||||
DELETE from place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
|
||||
END IF;
|
||||
|
||||
-- No - process it as a new insertion (hopefully of low rank or it will be slow)
|
||||
insert into placex (osm_type, osm_id, class, type, name,
|
||||
admin_level, address, extratags, geometry)
|
||||
values (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name,
|
||||
NEW.admin_level, NEW.address, NEW.extratags, NEW.geometry);
|
||||
|
||||
{% if debug %}RAISE WARNING 'insert done % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,NEW.name;{% endif %}
|
||||
|
||||
RETURN NEW;
|
||||
DELETE FROM placex where place_id = existingplacex.place_id;
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
-- Special case for polygon shape changes because they tend to be large and we can be a bit clever about how we handle them
|
||||
IF existing.geometry::text != NEW.geometry::text
|
||||
AND ST_GeometryType(existing.geometry) in ('ST_Polygon','ST_MultiPolygon')
|
||||
AND ST_GeometryType(NEW.geometry) in ('ST_Polygon','ST_MultiPolygon')
|
||||
THEN
|
||||
|
||||
-- Get the version of the geometry actually used (in placex table)
|
||||
select geometry from placex where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type into existinggeometry;
|
||||
|
||||
-- Performance limit
|
||||
IF st_area(NEW.geometry) < 0.000000001 AND st_area(existinggeometry) < 1 THEN
|
||||
|
||||
-- re-index points that have moved in / out of the polygon, could be done as a single query but postgres gets the index usage wrong
|
||||
update placex set indexed_status = 2 where indexed_status = 0
|
||||
AND ST_Intersects(NEW.geometry, placex.geometry)
|
||||
AND NOT ST_Intersects(existinggeometry, placex.geometry)
|
||||
AND rank_search > existingplacex.rank_search AND (rank_search < 28 or name is not null);
|
||||
|
||||
update placex set indexed_status = 2 where indexed_status = 0
|
||||
AND ST_Intersects(existinggeometry, placex.geometry)
|
||||
AND NOT ST_Intersects(NEW.geometry, placex.geometry)
|
||||
AND rank_search > existingplacex.rank_search AND (rank_search < 28 or name is not null);
|
||||
|
||||
END IF;
|
||||
-- Update the placex entry in-place.
|
||||
UPDATE placex
|
||||
SET name = NEW.name,
|
||||
address = NEW.address,
|
||||
parent_place_id = null,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
indexed_status = 2,
|
||||
geometry = NEW.geometry
|
||||
WHERE place_id = existingplacex.place_id;
|
||||
|
||||
-- If an address node which is part of a interpolation line changes
|
||||
-- mark this line for reparenting.
|
||||
-- (Already here, because interpolation lines are reindexed before nodes,
|
||||
-- so in the second call it would be too late.)
|
||||
IF NEW.osm_type='N'
|
||||
and coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
THEN
|
||||
result:= osmline_reinsert(NEW.osm_id, NEW.geometry);
|
||||
END IF;
|
||||
|
||||
|
||||
IF coalesce(existing.name::text, '') != coalesce(NEW.name::text, '')
|
||||
OR coalesce(existing.extratags::text, '') != coalesce(NEW.extratags::text, '')
|
||||
OR coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
OR coalesce(existing.admin_level, 15) != coalesce(NEW.admin_level, 15)
|
||||
OR existing.geometry::text != NEW.geometry::text
|
||||
THEN
|
||||
|
||||
update place set
|
||||
name = NEW.name,
|
||||
address = NEW.address,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
geometry = NEW.geometry
|
||||
where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
|
||||
|
||||
|
||||
IF NEW.class = 'boundary' AND NEW.type = 'postal_code' THEN
|
||||
IF NEW.address is NULL OR NOT NEW.address ? 'postcode' THEN
|
||||
-- postcode was deleted, no longer retain in placex
|
||||
DELETE FROM placex where place_id = existingplacex.place_id;
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
NEW.name := hstore('ref', NEW.address->'postcode');
|
||||
END IF;
|
||||
|
||||
IF NEW.class in ('boundary')
|
||||
AND ST_GeometryType(NEW.geometry) not in ('ST_Polygon','ST_MultiPolygon') THEN
|
||||
DELETE FROM placex where place_id = existingplacex.place_id;
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
update placex set
|
||||
name = NEW.name,
|
||||
address = NEW.address,
|
||||
parent_place_id = null,
|
||||
extratags = NEW.extratags,
|
||||
admin_level = NEW.admin_level,
|
||||
indexed_status = 2,
|
||||
geometry = NEW.geometry
|
||||
where place_id = existingplacex.place_id;
|
||||
|
||||
-- if a node(=>house), which is part of a interpolation line, changes (e.g. the street attribute) => mark this line for reparenting
|
||||
-- (already here, because interpolation lines are reindexed before nodes, so in the second call it would be too late)
|
||||
IF NEW.osm_type='N'
|
||||
and (coalesce(existing.address, ''::hstore) != coalesce(NEW.address, ''::hstore)
|
||||
or existing.geometry::text != NEW.geometry::text)
|
||||
THEN
|
||||
result:= osmline_reinsert(NEW.osm_id, NEW.geometry);
|
||||
END IF;
|
||||
|
||||
-- linked places should get potential new naming and addresses
|
||||
IF existingplacex.linked_place_id is not NULL THEN
|
||||
update placex x set
|
||||
name = p.name,
|
||||
extratags = p.extratags,
|
||||
indexed_status = 2
|
||||
from place p
|
||||
where x.place_id = existingplacex.linked_place_id
|
||||
-- Invalidate linked places: they potentially get a new name and addresses.
|
||||
IF existingplacex.linked_place_id is not NULL THEN
|
||||
UPDATE placex x
|
||||
SET name = p.name,
|
||||
extratags = p.extratags,
|
||||
indexed_status = 2
|
||||
FROM place p
|
||||
WHERE x.place_id = existingplacex.linked_place_id
|
||||
and x.indexed_status = 0
|
||||
and x.osm_type = p.osm_type
|
||||
and x.osm_id = p.osm_id
|
||||
and x.class = p.class;
|
||||
END IF;
|
||||
|
||||
IF coalesce(existing.name::text, '') != coalesce(NEW.name::text, '')
|
||||
THEN
|
||||
IF existingplacex.rank_address between 26 and 27 THEN
|
||||
-- When streets change their name, this may have an effect on POI objects
|
||||
-- with addr:street tags.
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE indexed_status = 0 and address ? 'street'
|
||||
and parent_place_id = existingplacex.place_id;
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE indexed_status = 0 and rank_search = 30 and address ? 'street'
|
||||
and ST_DWithin(NEW.geometry, geometry, 0.002);
|
||||
ELSEIF existingplacex.rank_address between 16 and 25 THEN
|
||||
-- When places change their name, this may have an effect on POI objects
|
||||
-- with addr:place tags.
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE indexed_status = 0 and address ? 'place' and rank_search = 30
|
||||
and parent_place_id = existingplacex.place_id;
|
||||
-- No update of surrounding objects, potentially too expensive.
|
||||
END IF;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- Abort the add (we modified the existing place instead)
|
||||
RETURN NULL;
|
||||
-- Invalidate dependent objects effected by name changes
|
||||
IF coalesce(existing.name::text, '') != coalesce(NEW.name::text, '')
|
||||
THEN
|
||||
IF existingplacex.rank_address between 26 and 27 THEN
|
||||
-- When streets change their name, this may have an effect on POI objects
|
||||
-- with addr:street tags.
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE indexed_status = 0 and address ? 'street'
|
||||
and parent_place_id = existingplacex.place_id;
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE indexed_status = 0 and rank_search = 30 and address ? 'street'
|
||||
and ST_DWithin(NEW.geometry, geometry, 0.002);
|
||||
ELSEIF existingplacex.rank_address between 16 and 25 THEN
|
||||
-- When places change their name, this may have an effect on POI objects
|
||||
-- with addr:place tags.
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE indexed_status = 0 and address ? 'place' and rank_search = 30
|
||||
and parent_place_id = existingplacex.place_id;
|
||||
-- No update of surrounding objects, potentially too expensive.
|
||||
END IF;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- Abort the insertion (we modified the existing place instead)
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user