mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-03-07 02:24:08 +00:00
revert importing of housenumber interpolations
This commit is contained in:
@@ -79,12 +79,12 @@ local table_definitions = {
|
||||
}
|
||||
},
|
||||
place_interpolation = {
|
||||
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
|
||||
ids = { type = 'way', id_column = 'osm_id' },
|
||||
columns = {
|
||||
{ column = 'type', type = 'text', not_null = true },
|
||||
{ column = 'address', type = 'hstore' },
|
||||
{ column = 'nodes', type = 'text', sql_type = 'bigint[]' },
|
||||
{ column = 'geometry', type = 'geometry', projection = 'WGS84', not_null = true },
|
||||
{ column = 'nodes', type = 'text', sql_type = 'bigint[]', not_null = true },
|
||||
{ column = 'geometry', type = 'linestring', projection = 'WGS84', not_null = true },
|
||||
},
|
||||
indexes = {
|
||||
{ column = 'nodes', method = 'gin' }
|
||||
@@ -387,6 +387,7 @@ function Place:grab_address_parts(data)
|
||||
|
||||
if atype ~= nil then
|
||||
if atype == 'main' then
|
||||
self.has_name = true
|
||||
self.address[strip_address_prefix(k)] = v
|
||||
count = count + 1
|
||||
elseif atype == 'extra' then
|
||||
@@ -707,38 +708,31 @@ function module.process_tags(o)
|
||||
local fallback = o:grab_name_parts{groups=NAME_FILTER}
|
||||
|
||||
-- address keys
|
||||
local fallback_address = (o:grab_address_parts{groups=ADDRESS_FILTER} > 0)
|
||||
if o:grab_address_parts{groups=ADDRESS_FILTER} > 0 and fallback == nil then
|
||||
fallback = {'place', 'house', address_fallback}
|
||||
end
|
||||
if o.address.country ~= nil and #o.address.country ~= 2 then
|
||||
o.address['country'] = nil
|
||||
end
|
||||
|
||||
if o.address.interpolation ~= nil
|
||||
and (o.address.housenumber == nil
|
||||
or string.find(o.address.housenumber, '^%d+%-%d+$') ~= nil) then
|
||||
if o:geometry_is_valid() then
|
||||
local extra_addr = nil
|
||||
for k, v in pairs(o.address) do
|
||||
if k ~= 'interpolation' then
|
||||
if extra_addr == nil then
|
||||
extra_addr = {}
|
||||
end
|
||||
extra_addr[k] = v
|
||||
if o.address.interpolation ~= nil and o.address.housenumber == nil
|
||||
and o.object.type == 'way' and o.object.nodes ~= nil then
|
||||
local extra_addr = nil
|
||||
for k, v in pairs(o.address) do
|
||||
if k ~= 'interpolation' then
|
||||
if extra_addr == nil then
|
||||
extra_addr = {}
|
||||
end
|
||||
extra_addr[k] = v
|
||||
end
|
||||
local nodes = nil
|
||||
if o.address.housenumber == nil and o.object.nodes ~= nil then
|
||||
nodes = '{' .. table.concat(o.object.nodes, ',') .. '}'
|
||||
end
|
||||
insert_row.place_interpolation{
|
||||
type = o.address.interpolation,
|
||||
address = extra_addr,
|
||||
nodes = nodes,
|
||||
geometry = o.geometry
|
||||
}
|
||||
fallback_address = false
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
insert_row.place_interpolation{
|
||||
type = o.address.interpolation,
|
||||
address = extra_addr,
|
||||
nodes = '{' .. table.concat(o.object.nodes, ',') .. '}',
|
||||
geometry = o.object:as_linestring()
|
||||
}
|
||||
end
|
||||
|
||||
-- collect main keys
|
||||
@@ -760,7 +754,7 @@ function module.process_tags(o)
|
||||
geometry = o.geometry
|
||||
}
|
||||
end
|
||||
elseif ktype == 'fallback' and (fallback_address or o.has_name) then
|
||||
elseif ktype == 'fallback' and o.has_name then
|
||||
fallback = {k, v, PlaceTransform.always}
|
||||
end
|
||||
end
|
||||
@@ -769,8 +763,6 @@ function module.process_tags(o)
|
||||
if o.num_entries == 0 then
|
||||
if fallback ~= nil then
|
||||
o:write_place(fallback[1], fallback[2], fallback[3])
|
||||
elseif fallback_address then
|
||||
o:write_place('place', 'house', address_fallback)
|
||||
elseif POSTCODE_FALLBACK and not postcode_collect
|
||||
and o.address.postcode ~= nil
|
||||
and o:geometry_is_valid() then
|
||||
|
||||
@@ -15,67 +15,63 @@ DECLARE
|
||||
existingplacex BIGINT[];
|
||||
|
||||
BEGIN
|
||||
-- Remove the place from the list of places to be deleted
|
||||
DELETE FROM place_interpolation_to_be_deleted pdel
|
||||
WHERE pdel.osm_type = NEW.osm_type and pdel.osm_id = NEW.osm_id;
|
||||
|
||||
SELECT * INTO existing FROM place_interpolation p
|
||||
WHERE p.osm_type = NEW.osm_type AND p.osm_id = NEW.osm_id;
|
||||
|
||||
IF NOT (NEW.type in ('odd', 'even', 'all') OR NEW.type similar to '[1-9]') THEN
|
||||
-- the new interpolation is illegal, simply remove existing entries
|
||||
DELETE FROM location_property_osmline o
|
||||
WHERE o.osm_type = NEW.osm_type AND o.osm_id = NEW.osm_id;
|
||||
DELETE FROM location_property_osmline o WHERE o.osm_id = NEW.osm_id;
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
-- Remove the place from the list of places to be deleted
|
||||
DELETE FROM place_interpolation_to_be_deleted pdel WHERE pdel.osm_id = NEW.osm_id;
|
||||
|
||||
SELECT * INTO existing FROM place_interpolation p WHERE p.osm_id = NEW.osm_id;
|
||||
|
||||
-- Get the existing entry from the interpolation table.
|
||||
SELECT array_agg(place_id) INTO existingplacex
|
||||
FROM location_property_osmline o WHERE o.osm_id = NEW.osm_id;
|
||||
|
||||
IF array_length(existingplacex, 1) is NULL THEN
|
||||
INSERT INTO location_property_osmline (osm_id, type, address, linegeo)
|
||||
VALUES (NEW.osm_id, NEW.type, NEW.address, NEW.geometry);
|
||||
ELSE
|
||||
-- Get the existing entry from the interpolation table.
|
||||
SELECT array_agg(place_id) INTO existingplacex
|
||||
FROM location_property_osmline o
|
||||
WHERE o.osm_type = NEW.osm_type AND o.osm_id = NEW.osm_id;
|
||||
|
||||
IF array_length(existingplacex, 1) is NULL THEN
|
||||
INSERT INTO location_property_osmline (osm_type, osm_id, type, address, linegeo)
|
||||
VALUES (NEW.osm_type, NEW.osm_id, NEW.type, NEW.address, NEW.geometry);
|
||||
ELSE
|
||||
-- Update the interpolation table:
|
||||
-- The first entry gets the original data, all other entries
|
||||
-- are removed and will be recreated on indexing.
|
||||
-- (An interpolation can be split up, if it has more than 2 address nodes)
|
||||
-- Update unconditionally here as the changes might be coming from the
|
||||
-- nodes on the interpolation.
|
||||
UPDATE location_property_osmline
|
||||
SET type = NEW.type,
|
||||
address = NEW.address,
|
||||
linegeo = NEW.geometry,
|
||||
startnumber = null,
|
||||
indexed_status = 1
|
||||
WHERE place_id = existingplacex[1];
|
||||
IF array_length(existingplacex, 1) > 1 THEN
|
||||
DELETE FROM location_property_osmline
|
||||
WHERE place_id = any(existingplacex[2:]);
|
||||
END IF;
|
||||
-- Update the interpolation table:
|
||||
-- The first entry gets the original data, all other entries
|
||||
-- are removed and will be recreated on indexing.
|
||||
-- (An interpolation can be split up, if it has more than 2 address nodes)
|
||||
-- Update unconditionally here as the changes might be coming from the
|
||||
-- nodes on the interpolation.
|
||||
UPDATE location_property_osmline
|
||||
SET type = NEW.type,
|
||||
address = NEW.address,
|
||||
linegeo = NEW.geometry,
|
||||
startnumber = null,
|
||||
indexed_status = 1
|
||||
WHERE place_id = existingplacex[1];
|
||||
IF array_length(existingplacex, 1) > 1 THEN
|
||||
DELETE FROM location_property_osmline WHERE place_id = any(existingplacex[2:]);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- need to invalidate nodes because they might copy address info
|
||||
IF NEW.address is not NULL
|
||||
AND (existing.osm_type is NULL
|
||||
OR coalesce(existing.address, ''::hstore) != NEW.address)
|
||||
THEN
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE osm_type = 'N' AND osm_id = ANY(NEW.nodes)
|
||||
AND indexed_status = 0;
|
||||
END IF;
|
||||
-- need to invalidate nodes because they might copy address info
|
||||
IF NEW.address is not NULL
|
||||
AND (existing.osm_id is NULL
|
||||
OR coalesce(existing.address, ''::hstore) != NEW.address)
|
||||
THEN
|
||||
UPDATE placex SET indexed_status = 2
|
||||
WHERE osm_type = 'N' AND osm_id = ANY(NEW.nodes) AND indexed_status = 0;
|
||||
END IF;
|
||||
|
||||
-- finally update/insert place_interpolation itself
|
||||
|
||||
IF existing.osm_type is not NULL THEN
|
||||
IF existing.osm_id is not NULL THEN
|
||||
-- Always updates as the nodes with the housenumber might be the reason
|
||||
-- for the change.
|
||||
UPDATE place_interpolation p
|
||||
SET type = NEW.type,
|
||||
address = NEW.address,
|
||||
nodes = NEW.nodes,
|
||||
geometry = NEW.geometry
|
||||
WHERE p.osm_type = NEW.osm_type AND p.osm_id = NEW.osm_id;
|
||||
WHERE p.osm_id = NEW.osm_id;
|
||||
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
@@ -91,15 +87,15 @@ CREATE OR REPLACE FUNCTION place_interpolation_delete()
|
||||
DECLARE
|
||||
deferred BOOLEAN;
|
||||
BEGIN
|
||||
{% if debug %}RAISE WARNING 'Delete for % % %/%', OLD.osm_type, OLD.osm_id, OLD.class, OLD.type;{% endif %}
|
||||
{% if debug %}RAISE WARNING 'Delete for interpolation %', OLD.osm_id;{% endif %}
|
||||
|
||||
INSERT INTO place_interpolation_to_be_deleted (osm_type, osm_id)
|
||||
VALUES(OLD.osm_type, OLD.osm_id);
|
||||
INSERT INTO place_interpolation_to_be_deleted (osm_id) VALUES(OLD.osm_id);
|
||||
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION get_interpolation_address(in_address HSTORE, wayid BIGINT)
|
||||
RETURNS HSTORE
|
||||
AS $$
|
||||
@@ -111,8 +107,7 @@ BEGIN
|
||||
RETURN in_address;
|
||||
END IF;
|
||||
|
||||
SELECT nodes INTO waynodes FROM place_interpolation
|
||||
WHERE osm_type = 'W' AND osm_id = wayid;
|
||||
SELECT nodes INTO waynodes FROM place_interpolation WHERE osm_id = wayid;
|
||||
|
||||
IF array_upper(waynodes, 1) IS NOT NULL THEN
|
||||
FOR location IN
|
||||
@@ -184,22 +179,7 @@ BEGIN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
IF NEW.address is not NULL AND NEW.address ? 'housenumber' THEN
|
||||
IF NEW.address->'housenumber' not similar to '[0-9]+-[0-9]+' THEN
|
||||
-- housenumber needs to look like an interpolation
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
centroid := ST_Centroid(NEW.linegeo);
|
||||
-- interpolation of a housenumber, make sure we have a line to interpolate on
|
||||
NEW.geometry := ST_MakeLine(centroid, ST_Project(centroid, 0.0000001, 0));
|
||||
ELSE
|
||||
centroid := get_center_point(NEW.linegeo);
|
||||
IF NEW.osm_type != 'W' THEN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
centroid := get_center_point(NEW.linegeo);
|
||||
NEW.indexed_status := 1; --STATUS_NEW
|
||||
NEW.country_code := lower(get_country_code(centroid));
|
||||
|
||||
@@ -230,7 +210,6 @@ DECLARE
|
||||
sectiongeo GEOMETRY;
|
||||
postcode TEXT;
|
||||
stepmod SMALLINT;
|
||||
splitstring TEXT[];
|
||||
BEGIN
|
||||
-- deferred delete
|
||||
IF OLD.indexed_status = 100 THEN
|
||||
@@ -261,158 +240,132 @@ BEGIN
|
||||
stepmod := NULL;
|
||||
END IF;
|
||||
|
||||
IF NEW.address is not NULL AND NEW.address ? 'housenumer' THEN
|
||||
-- interpolation interval is in housenumber
|
||||
splitstring := string_to_array(NEW.address->'housenumber', '-');
|
||||
NEW.startnumber := (splitstring[1])::INTEGER;
|
||||
NEW.endnumber := (splitstring[2])::INTEGER;
|
||||
SELECT nodes INTO waynodes FROM place_interpolation WHERE osm_id = NEW.osm_id;
|
||||
|
||||
IF stepmod is not NULL THEN
|
||||
IF NEW.startnumber % NEW.step != stepmod THEN
|
||||
NEW.startnumber := NEW.startnumber + 1;
|
||||
END IF;
|
||||
IF NEW.endnumber % NEW.step != stepmod THEN
|
||||
NEW.endnumber := NEW.endnumber - 1;
|
||||
END IF;
|
||||
ELSE
|
||||
NEW.endnumber := NEW.startnumber + ((NEW.endnumber - NEW.startnumber) / NEW.step) * NEW.step;
|
||||
END IF;
|
||||
|
||||
IF NEW.startnumber = NEW.endnumber THEN
|
||||
NEW.geometry := ST_PointN(NEW.geometry, 1);
|
||||
ELSEIF NEW.startnumber > NEW.endnumber THEN
|
||||
NEW.startnumber := NULL;
|
||||
END IF;
|
||||
ELSE
|
||||
-- classic interpolation way
|
||||
SELECT nodes INTO waynodes
|
||||
FROM place_interpolation WHERE osm_type = NEW.osm_type AND osm_id = NEW.osm_id;
|
||||
|
||||
IF array_upper(waynodes, 1) IS NULL THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
linegeo := null;
|
||||
SELECT null::integer as hnr INTO prevnode;
|
||||
|
||||
-- Go through all nodes on the interpolation line that have a housenumber.
|
||||
FOR nextnode IN
|
||||
SELECT DISTINCT ON (nodeidpos)
|
||||
osm_id, address, geometry,
|
||||
-- Take the postcode from the node only if it has a housenumber itself.
|
||||
-- Note that there is a corner-case where the node has a wrongly
|
||||
-- formatted postcode and therefore 'postcode' contains a derived
|
||||
-- variant.
|
||||
CASE WHEN address ? 'postcode' THEN placex.postcode ELSE NULL::text END as postcode,
|
||||
(address->'housenumber')::integer as hnr
|
||||
FROM placex, generate_series(1, array_upper(waynodes, 1)) nodeidpos
|
||||
WHERE osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT
|
||||
and address is not NULL and address ? 'housenumber'
|
||||
and address->'housenumber' ~ '^[0-9]{1,6}$'
|
||||
and ST_Distance(NEW.linegeo, geometry) < 0.0005
|
||||
ORDER BY nodeidpos
|
||||
LOOP
|
||||
{% if debug %}RAISE WARNING 'processing point % (%)', nextnode.hnr, ST_AsText(nextnode.geometry);{% endif %}
|
||||
IF linegeo is null THEN
|
||||
linegeo := NEW.linegeo;
|
||||
ELSE
|
||||
splitpoint := ST_LineLocatePoint(linegeo, nextnode.geometry);
|
||||
IF splitpoint = 0 THEN
|
||||
-- Corner case where the splitpoint falls on the first point
|
||||
-- and thus would not return a geometry. Skip that section.
|
||||
sectiongeo := NULL;
|
||||
ELSEIF splitpoint = 1 THEN
|
||||
-- Point is at the end of the line.
|
||||
sectiongeo := linegeo;
|
||||
linegeo := NULL;
|
||||
ELSE
|
||||
-- Split the line.
|
||||
sectiongeo := ST_LineSubstring(linegeo, 0, splitpoint);
|
||||
linegeo := ST_LineSubstring(linegeo, splitpoint, 1);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
IF prevnode.hnr is not null
|
||||
-- Check if there are housenumbers to interpolate between the
|
||||
-- regularly mapped housenumbers.
|
||||
-- (Conveniently also fails if one of the house numbers is not a number.)
|
||||
and abs(prevnode.hnr - nextnode.hnr) > NEW.step
|
||||
-- If the interpolation geometry is broken or two nodes are at the
|
||||
-- same place, then splitting might produce a point. Ignore that.
|
||||
and ST_GeometryType(sectiongeo) = 'ST_LineString'
|
||||
THEN
|
||||
IF prevnode.hnr < nextnode.hnr THEN
|
||||
startnumber := prevnode.hnr;
|
||||
endnumber := nextnode.hnr;
|
||||
ELSE
|
||||
startnumber := nextnode.hnr;
|
||||
endnumber := prevnode.hnr;
|
||||
sectiongeo := ST_Reverse(sectiongeo);
|
||||
END IF;
|
||||
|
||||
-- Adjust the interpolation, so that only inner housenumbers
|
||||
-- are taken into account.
|
||||
IF stepmod is null THEN
|
||||
newstart := startnumber + NEW.step;
|
||||
ELSE
|
||||
newstart := startnumber + 1;
|
||||
moddiff := newstart % NEW.step - stepmod;
|
||||
IF moddiff < 0 THEN
|
||||
newstart := newstart + (NEW.step + moddiff);
|
||||
ELSE
|
||||
newstart := newstart + moddiff;
|
||||
END IF;
|
||||
END IF;
|
||||
newend := newstart + ((endnumber - 1 - newstart) / NEW.step) * NEW.step;
|
||||
|
||||
-- If newstart and newend are the same, then this returns a point.
|
||||
sectiongeo := ST_LineSubstring(sectiongeo,
|
||||
(newstart - startnumber)::float / (endnumber - startnumber)::float,
|
||||
(newend - startnumber)::float / (endnumber - startnumber)::float);
|
||||
startnumber := newstart;
|
||||
endnumber := newend;
|
||||
|
||||
-- determine postcode
|
||||
postcode := coalesce(prevnode.postcode, nextnode.postcode, postcode);
|
||||
IF postcode is NULL and NEW.parent_place_id > 0 THEN
|
||||
SELECT placex.postcode FROM placex
|
||||
WHERE place_id = NEW.parent_place_id INTO postcode;
|
||||
END IF;
|
||||
IF postcode is NULL THEN
|
||||
postcode := get_nearest_postcode(NEW.country_code, nextnode.geometry);
|
||||
END IF;
|
||||
|
||||
-- Add the interpolation. If this is the first segment, just modify
|
||||
-- the interpolation to be inserted, otherwise add an additional one
|
||||
-- (marking it indexed already).
|
||||
IF NEW.startnumber IS NULL THEN
|
||||
NEW.startnumber := startnumber;
|
||||
NEW.endnumber := endnumber;
|
||||
NEW.linegeo := ST_ReducePrecision(sectiongeo, 0.0000001);
|
||||
NEW.postcode := postcode;
|
||||
ELSE
|
||||
INSERT INTO location_property_osmline
|
||||
(linegeo, partition, osm_type, osm_id, parent_place_id,
|
||||
startnumber, endnumber, step, type,
|
||||
address, postcode, country_code,
|
||||
geometry_sector, indexed_status)
|
||||
VALUES (ST_ReducePrecision(sectiongeo, 0.0000001),
|
||||
NEW.partition, NEW.osm_type, NEW.osm_id, NEW.parent_place_id,
|
||||
startnumber, endnumber, NEW.step, NEW.type,
|
||||
NEW.address, postcode,
|
||||
NEW.country_code, NEW.geometry_sector, 0);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- early break if we are out of line string,
|
||||
-- might happen when a line string loops back on itself
|
||||
IF linegeo is null or ST_GeometryType(linegeo) != 'ST_LineString' THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
prevnode := nextnode;
|
||||
END LOOP;
|
||||
IF array_upper(waynodes, 1) IS NULL THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
linegeo := null;
|
||||
SELECT null::integer as hnr INTO prevnode;
|
||||
|
||||
-- Go through all nodes on the interpolation line that have a housenumber.
|
||||
FOR nextnode IN
|
||||
SELECT DISTINCT ON (nodeidpos)
|
||||
osm_id, address, geometry,
|
||||
-- Take the postcode from the node only if it has a housenumber itself.
|
||||
-- Note that there is a corner-case where the node has a wrongly
|
||||
-- formatted postcode and therefore 'postcode' contains a derived
|
||||
-- variant.
|
||||
CASE WHEN address ? 'postcode' THEN placex.postcode ELSE NULL::text END as postcode,
|
||||
(address->'housenumber')::integer as hnr
|
||||
FROM placex, generate_series(1, array_upper(waynodes, 1)) nodeidpos
|
||||
WHERE osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT
|
||||
and address is not NULL and address ? 'housenumber'
|
||||
and address->'housenumber' ~ '^[0-9]{1,6}$'
|
||||
and ST_Distance(NEW.linegeo, geometry) < 0.0005
|
||||
ORDER BY nodeidpos
|
||||
LOOP
|
||||
{% if debug %}RAISE WARNING 'processing point % (%)', nextnode.hnr, ST_AsText(nextnode.geometry);{% endif %}
|
||||
IF linegeo is null THEN
|
||||
linegeo := NEW.linegeo;
|
||||
ELSE
|
||||
splitpoint := ST_LineLocatePoint(linegeo, nextnode.geometry);
|
||||
IF splitpoint = 0 THEN
|
||||
-- Corner case where the splitpoint falls on the first point
|
||||
-- and thus would not return a geometry. Skip that section.
|
||||
sectiongeo := NULL;
|
||||
ELSEIF splitpoint = 1 THEN
|
||||
-- Point is at the end of the line.
|
||||
sectiongeo := linegeo;
|
||||
linegeo := NULL;
|
||||
ELSE
|
||||
-- Split the line.
|
||||
sectiongeo := ST_LineSubstring(linegeo, 0, splitpoint);
|
||||
linegeo := ST_LineSubstring(linegeo, splitpoint, 1);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
IF prevnode.hnr is not null
|
||||
-- Check if there are housenumbers to interpolate between the
|
||||
-- regularly mapped housenumbers.
|
||||
-- (Conveniently also fails if one of the house numbers is not a number.)
|
||||
and abs(prevnode.hnr - nextnode.hnr) > NEW.step
|
||||
-- If the interpolation geometry is broken or two nodes are at the
|
||||
-- same place, then splitting might produce a point. Ignore that.
|
||||
and ST_GeometryType(sectiongeo) = 'ST_LineString'
|
||||
THEN
|
||||
IF prevnode.hnr < nextnode.hnr THEN
|
||||
startnumber := prevnode.hnr;
|
||||
endnumber := nextnode.hnr;
|
||||
ELSE
|
||||
startnumber := nextnode.hnr;
|
||||
endnumber := prevnode.hnr;
|
||||
sectiongeo := ST_Reverse(sectiongeo);
|
||||
END IF;
|
||||
|
||||
-- Adjust the interpolation, so that only inner housenumbers
|
||||
-- are taken into account.
|
||||
IF stepmod is null THEN
|
||||
newstart := startnumber + NEW.step;
|
||||
ELSE
|
||||
newstart := startnumber + 1;
|
||||
moddiff := newstart % NEW.step - stepmod;
|
||||
IF moddiff < 0 THEN
|
||||
newstart := newstart + (NEW.step + moddiff);
|
||||
ELSE
|
||||
newstart := newstart + moddiff;
|
||||
END IF;
|
||||
END IF;
|
||||
newend := newstart + ((endnumber - 1 - newstart) / NEW.step) * NEW.step;
|
||||
|
||||
-- If newstart and newend are the same, then this returns a point.
|
||||
sectiongeo := ST_LineSubstring(sectiongeo,
|
||||
(newstart - startnumber)::float / (endnumber - startnumber)::float,
|
||||
(newend - startnumber)::float / (endnumber - startnumber)::float);
|
||||
startnumber := newstart;
|
||||
endnumber := newend;
|
||||
|
||||
-- determine postcode
|
||||
postcode := coalesce(prevnode.postcode, nextnode.postcode, postcode);
|
||||
IF postcode is NULL and NEW.parent_place_id > 0 THEN
|
||||
SELECT placex.postcode FROM placex
|
||||
WHERE place_id = NEW.parent_place_id INTO postcode;
|
||||
END IF;
|
||||
IF postcode is NULL THEN
|
||||
postcode := get_nearest_postcode(NEW.country_code, nextnode.geometry);
|
||||
END IF;
|
||||
|
||||
-- Add the interpolation. If this is the first segment, just modify
|
||||
-- the interpolation to be inserted, otherwise add an additional one
|
||||
-- (marking it indexed already).
|
||||
IF NEW.startnumber IS NULL THEN
|
||||
NEW.startnumber := startnumber;
|
||||
NEW.endnumber := endnumber;
|
||||
NEW.linegeo := ST_ReducePrecision(sectiongeo, 0.0000001);
|
||||
NEW.postcode := postcode;
|
||||
ELSE
|
||||
INSERT INTO location_property_osmline
|
||||
(linegeo, partition, osm_id, parent_place_id,
|
||||
startnumber, endnumber, step, type,
|
||||
address, postcode, country_code,
|
||||
geometry_sector, indexed_status)
|
||||
VALUES (ST_ReducePrecision(sectiongeo, 0.0000001),
|
||||
NEW.partition, NEW.osm_id, NEW.parent_place_id,
|
||||
startnumber, endnumber, NEW.step, NEW.type,
|
||||
NEW.address, postcode,
|
||||
NEW.country_code, NEW.geometry_sector, 0);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- early break if we are out of line string,
|
||||
-- might happen when a line string loops back on itself
|
||||
IF linegeo is null or ST_GeometryType(linegeo) != 'ST_LineString' THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
prevnode := nextnode;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
|
||||
@@ -53,10 +53,8 @@ BEGIN
|
||||
-- See if we can inherit additional address tags from an interpolation.
|
||||
-- These will become permanent.
|
||||
FOR location IN
|
||||
SELECT address as address
|
||||
FROM place_interpolation
|
||||
WHERE p.osm_id = any(place_interpolation.nodes)
|
||||
AND address is not NULL AND not address ? 'housenumber'
|
||||
SELECT address FROM place_interpolation
|
||||
WHERE ARRAY[p.osm_id] && place_interpolation.nodes AND address is not NULL
|
||||
LOOP
|
||||
result.address := location.address || result.address;
|
||||
END LOOP;
|
||||
|
||||
@@ -630,12 +630,12 @@ BEGIN
|
||||
-- delete from place_interpolation table
|
||||
ALTER TABLE place_interpolation DISABLE TRIGGER place_interpolation_before_delete;
|
||||
DELETE FROM place_interpolation p USING place_interpolation_to_be_deleted d
|
||||
WHERE p.osm_type = d.osm_type AND p.osm_id = d.osm_id;
|
||||
WHERE p.osm_id = d.osm_id;
|
||||
ALTER TABLE place_interpolation ENABLE TRIGGER place_interpolation_before_delete;
|
||||
|
||||
UPDATE location_property_osmline o SET indexed_status = 100
|
||||
FROM place_interpolation_to_be_deleted d
|
||||
WHERE o.osm_type = d.osm_Type AND o.osm_id = d.osm_id;
|
||||
WHERE o.osm_id = d.osm_id;
|
||||
|
||||
TRUNCATE TABLE place_interpolation_to_be_deleted;
|
||||
|
||||
|
||||
@@ -75,7 +75,6 @@ CREATE INDEX IF NOT EXISTS idx_osmline_parent_osm_id
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS place_interpolation_to_be_deleted (
|
||||
osm_type CHAR(1) NOT NULL,
|
||||
osm_id BIGINT NOT NULL
|
||||
);
|
||||
---
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
DROP TABLE IF EXISTS location_property_osmline;
|
||||
CREATE TABLE location_property_osmline (
|
||||
place_id BIGINT NOT NULL,
|
||||
osm_type CHAR(1) NOT NULL,
|
||||
osm_id BIGINT NOT NULL,
|
||||
parent_place_id BIGINT,
|
||||
geometry_sector INTEGER NOT NULL,
|
||||
@@ -19,7 +18,7 @@ CREATE TABLE location_property_osmline (
|
||||
step SMALLINT,
|
||||
partition SMALLINT NOT NULL,
|
||||
indexed_status SMALLINT NOT NULL,
|
||||
linegeo GEOMETRY NOT NULL,
|
||||
linegeo GEOMETRY(Geometry, 4326) NOT NULL,
|
||||
address HSTORE,
|
||||
token_info JSONB, -- custom column for tokenizer use only
|
||||
postcode TEXT,
|
||||
|
||||
@@ -225,8 +225,8 @@ async def load_data(dsn: str, threads: int) -> None:
|
||||
|
||||
# Interpolations need to be copied separately
|
||||
await pool.put_query("""
|
||||
INSERT INTO location_property_osmline (osm_type, osm_id, type, address, linegeo)
|
||||
SELECT osm_type, osm_id, type, address, geometry
|
||||
INSERT INTO location_property_osmline (osm_id, type, address, linegeo)
|
||||
SELECT osm_id, type, address, geometry
|
||||
FROM place_interpolation
|
||||
""", None)
|
||||
|
||||
|
||||
@@ -378,8 +378,8 @@ Feature: Import of address interpolations
|
||||
|
||||
Scenario: Ways without node entries are ignored
|
||||
Given the interpolations
|
||||
| osm | type | geometry |
|
||||
| W1 | even | 1 1, 1 1.001 |
|
||||
| osm | type | geometry | nodes |
|
||||
| W1 | even | 1 1, 1 1.001 | 34,45 |
|
||||
And the named places
|
||||
| osm | class | type | geometry |
|
||||
| W10 | highway | residential | 1 1, 1 1.001 |
|
||||
|
||||
@@ -287,38 +287,6 @@ Feature: Searching of house numbers
|
||||
| N1 |
|
||||
|
||||
|
||||
Scenario: Interpolations are found according to their type
|
||||
Given the grid
|
||||
| 10 | | 11 |
|
||||
| 100 | | 101 |
|
||||
| 20 | | 21 |
|
||||
And the places
|
||||
| osm | class | type | name | geometry |
|
||||
| W100 | highway | residential | Ringstr | 100, 101 |
|
||||
And the places
|
||||
| osm | class | type | addr+interpolation | geometry |
|
||||
| W10 | place | houses | even | 10, 11 |
|
||||
| W20 | place | houses | odd | 20, 21 |
|
||||
And the places
|
||||
| osm | class | type | housenr | geometry |
|
||||
| N10 | place | house | 10 | 10 |
|
||||
| N11 | place | house | 20 | 11 |
|
||||
| N20 | place | house | 11 | 20 |
|
||||
| N21 | place | house | 21 | 21 |
|
||||
And the ways
|
||||
| id | nodes |
|
||||
| 10 | 10, 11 |
|
||||
| 20 | 20, 21 |
|
||||
When importing
|
||||
When geocoding "Ringstr 12"
|
||||
Then the result set contains
|
||||
| object |
|
||||
| W10 |
|
||||
When geocoding "Ringstr 13"
|
||||
Then the result set contains
|
||||
| object |
|
||||
| W20 |
|
||||
|
||||
Scenario: A housenumber with interpolation is found
|
||||
Given the places
|
||||
| osm | class | type | housenr | addr+interpolation | geometry |
|
||||
|
||||
@@ -20,9 +20,9 @@ Feature: Import of interpolations
|
||||
| object | class | type |
|
||||
| W13002 | place | city |
|
||||
And place_interpolation contains exactly
|
||||
| object | type | address!dict | nodes!ints | geometry!wkt |
|
||||
| W13001 | odd | "street": "Blumenstrasse" | 1,2 | 1,2 |
|
||||
| W13002 | even | - | 1,2 | 1,2 |
|
||||
| osm_id | type | address!dict | nodes!ints | geometry!wkt |
|
||||
| 13001 | odd | "street": "Blumenstrasse" | 1,2 | 1,2 |
|
||||
| 13002 | even | - | 1,2 | 1,2 |
|
||||
|
||||
Scenario: Address interpolation with housenumber
|
||||
When loading osm data
|
||||
@@ -33,12 +33,10 @@ Feature: Import of interpolations
|
||||
n4
|
||||
w34 Taddr:interpolation=all,addr:housenumber=2-4,building=yes Nn1,n2,n3,n4,n1
|
||||
w35 Taddr:interpolation=all,addr:housenumber=5,building=yes Nn1,n2,n3,n4,n1
|
||||
w36 Taddr:interpolation=all,addr:housenumber=2a-c,building=yes Nn1,n2,n3,n4,n1
|
||||
w36 Taddr:interpolation=all,addr:housenumber=2a-c Nn1,n2,n3,n4,n1
|
||||
"""
|
||||
Then place contains exactly
|
||||
| object | class | type | address!dict |
|
||||
| w35 | building | yes | "housenumber" : "5", "interpolation": "all" |
|
||||
| w36 | building | yes | "housenumber" : "2a-c", "interpolation": "all" |
|
||||
Then place_interpolation contains exactly
|
||||
| object | type | address!dict | nodes!ints | geometry!wkt |
|
||||
| W34 | all | "housenumber": "2-4" | - | (1,2,3,4,1) |
|
||||
| object | class | type | address!dict |
|
||||
| W35 | building | yes | "housenumber": "5", "interpolation": "all" |
|
||||
| W34 | building | yes | "housenumber": "2-4", "interpolation": "all" |
|
||||
| W36 | place | house | "housenumber": "2a-c", "interpolation": "all" |
|
||||
|
||||
@@ -30,8 +30,8 @@ Feature: Updates of address interpolation objects
|
||||
| N2 | place | house |
|
||||
| W33 | highway | residential |
|
||||
And place_interpolation contains exactly
|
||||
| object | type |
|
||||
| W99 | odd |
|
||||
| osm_id | type |
|
||||
| 99 | odd |
|
||||
When indexing
|
||||
Then placex contains exactly
|
||||
| object | class | type |
|
||||
@@ -55,8 +55,8 @@ Feature: Updates of address interpolation objects
|
||||
| N1 | place | house |
|
||||
| N2 | place | house |
|
||||
And place_interpolation contains exactly
|
||||
| object | type |
|
||||
| W99 | odd |
|
||||
| osm_id | type |
|
||||
| 99 | odd |
|
||||
|
||||
When updating osm data
|
||||
"""
|
||||
@@ -67,7 +67,7 @@ Feature: Updates of address interpolation objects
|
||||
| N1 | place | house |
|
||||
| N2 | place | house |
|
||||
And place_interpolation contains exactly
|
||||
| object |
|
||||
| osm_id |
|
||||
When indexing
|
||||
Then placex contains exactly
|
||||
| object | class | type |
|
||||
@@ -92,7 +92,7 @@ Feature: Updates of address interpolation objects
|
||||
| W33 | highway | residential |
|
||||
| W99 | highway | residential |
|
||||
And place_interpolation contains exactly
|
||||
| object |
|
||||
| osm_id |
|
||||
|
||||
When updating osm data
|
||||
"""
|
||||
@@ -104,8 +104,8 @@ Feature: Updates of address interpolation objects
|
||||
| N2 | place | house |
|
||||
| W33 | highway | residential |
|
||||
And place_interpolation contains exactly
|
||||
| object | type |
|
||||
| W99 | odd |
|
||||
| osm_id | type |
|
||||
| 99 | odd |
|
||||
When indexing
|
||||
Then placex contains exactly
|
||||
| object | class | type |
|
||||
@@ -129,8 +129,8 @@ Feature: Updates of address interpolation objects
|
||||
| N1 | place | house |
|
||||
| N2 | place | house |
|
||||
And place_interpolation contains exactly
|
||||
| object | type |
|
||||
| W99 | odd |
|
||||
| osm_id | type |
|
||||
| 99 | odd |
|
||||
|
||||
When updating osm data
|
||||
"""
|
||||
@@ -142,7 +142,7 @@ Feature: Updates of address interpolation objects
|
||||
| N2 | place | house |
|
||||
| W99 | highway | residential |
|
||||
And place_interpolation contains exactly
|
||||
| object |
|
||||
| osm_id |
|
||||
When indexing
|
||||
Then placex contains exactly
|
||||
| object | class | type |
|
||||
|
||||
@@ -113,8 +113,8 @@ Feature: Update of postcode only objects
|
||||
| N1 | place | house |
|
||||
| N2 | place | house |
|
||||
And place_interpolation contains exactly
|
||||
| object | type |
|
||||
| W34 | odd |
|
||||
| osm_id | type |
|
||||
| 34 | odd |
|
||||
|
||||
When updating osm data
|
||||
"""
|
||||
@@ -128,7 +128,7 @@ Feature: Update of postcode only objects
|
||||
| object | postcode |
|
||||
| W34 | 4456 |
|
||||
And place_interpolation contains exactly
|
||||
| object |
|
||||
| osm_id |
|
||||
When indexing
|
||||
Then location_property_osmline contains exactly
|
||||
| osm_id |
|
||||
@@ -163,8 +163,8 @@ Feature: Update of postcode only objects
|
||||
| N2 | place | house |
|
||||
| W33 | highway | residential |
|
||||
And place_interpolation contains exactly
|
||||
| object | type |
|
||||
| W34 | odd |
|
||||
| osm_id | type |
|
||||
| 34 | odd |
|
||||
And place_postcode contains exactly
|
||||
| object |
|
||||
When indexing
|
||||
|
||||
@@ -135,15 +135,12 @@ def import_place_interpolations(row_factory, datatable, node_grid):
|
||||
"""
|
||||
for row in datatable[1:]:
|
||||
data = PlaceColumn(node_grid).add_row(datatable[0], row, False)
|
||||
assert data.columns['osm_type'] == 'W'
|
||||
|
||||
if 'nodes' in data.columns:
|
||||
nodes = [int(x) for x in data.columns['nodes'].split(',')]
|
||||
else:
|
||||
nodes = None
|
||||
|
||||
params = {'osm_type': data.columns['osm_type'], 'osm_id': data.columns['osm_id'],
|
||||
params = {'osm_id': data.columns['osm_id'],
|
||||
'type': data.columns['type'],
|
||||
'address': data.columns.get('address'), 'nodes': nodes,
|
||||
'address': data.columns.get('address'),
|
||||
'nodes': [int(x) for x in data.columns['nodes'].split(',')],
|
||||
'geometry': pysql.SQL(data.get_wkt())}
|
||||
|
||||
row_factory('place_interpolation', **params)
|
||||
@@ -275,15 +272,12 @@ def update_place_interpolations(db_conn, row_factory, update_config, datatable,
|
||||
"""
|
||||
for row in datatable[1:]:
|
||||
data = PlaceColumn(node_grid).add_row(datatable[0], row, False)
|
||||
assert data.columns['osm_type'] == 'W'
|
||||
|
||||
if 'nodes' in data.columns:
|
||||
nodes = [int(x) for x in data.columns['nodes'].split(',')]
|
||||
else:
|
||||
nodes = None
|
||||
|
||||
params = {'osm_type': data.columns['osm_type'], 'osm_id': data.columns['osm_id'],
|
||||
params = {'osm_id': data.columns['osm_id'],
|
||||
'type': data.columns['type'],
|
||||
'address': data.columns.get('address'), 'nodes': nodes,
|
||||
'address': data.columns.get('address'),
|
||||
'nodes': [int(x) for x in data.columns['nodes'].split(',')],
|
||||
'geometry': pysql.SQL(data.get_wkt())}
|
||||
|
||||
row_factory('place_interpolation', **params)
|
||||
@@ -310,8 +304,8 @@ def do_delete_place(db_conn, update_config, node_grid, otype, oid):
|
||||
cur.execute('TRUNCATE place_to_be_deleted')
|
||||
cur.execute('DELETE FROM place WHERE osm_type = %s and osm_id = %s',
|
||||
(otype, oid))
|
||||
cur.execute('DELETE FROM place_interpolation WHERE osm_type = %s and osm_id = %s',
|
||||
(otype, oid))
|
||||
cur.execute('DELETE FROM place_interpolation WHERE osm_id = %s',
|
||||
(oid, ))
|
||||
cur.execute('SELECT flush_deleted_places()')
|
||||
if otype == 'N':
|
||||
cur.execute('DELETE FROM place_entrance WHERE osm_id = %s',
|
||||
|
||||
@@ -251,8 +251,7 @@ def place_interpolation_table(temp_db_with_extensions, table_factory):
|
||||
""" Create an empty version of the place_interpolation table.
|
||||
"""
|
||||
table_factory('place_interpolation',
|
||||
"""osm_type char(1) NOT NULL,
|
||||
osm_id bigint NOT NULL,
|
||||
"""osm_id bigint NOT NULL,
|
||||
type TEXT,
|
||||
address HSTORE,
|
||||
nodes BIGINT[],
|
||||
@@ -266,9 +265,9 @@ def place_interpolation_row(place_interpolation_table, temp_db_cursor):
|
||||
"""
|
||||
idseq = itertools.count(30001)
|
||||
|
||||
def _insert(osm_type='N', osm_id=None, typ='odd', address=None,
|
||||
def _insert(osm_id=None, typ='odd', address=None,
|
||||
nodes=None, geom='LINESTRING(0.1 0.21, 0.1 0.2)'):
|
||||
params = {'osm_type': osm_type, 'osm_id': osm_id or next(idseq),
|
||||
params = {'osm_id': osm_id or next(idseq),
|
||||
'type': typ, 'address': address, 'nodes': nodes,
|
||||
'geometry': _with_srid(geom)}
|
||||
temp_db_cursor.insert_row('place_interpolation', **params)
|
||||
@@ -319,11 +318,10 @@ def osmline_table(temp_db_with_extensions, load_sql):
|
||||
def osmline_row(osmline_table, temp_db_cursor):
|
||||
idseq = itertools.count(20001)
|
||||
|
||||
def _add(osm_type='W', osm_id=None, geom='LINESTRING(12.0 11.0, 12.003 11.0)'):
|
||||
def _add(osm_id=None, geom='LINESTRING(12.0 11.0, 12.003 11.0)'):
|
||||
return temp_db_cursor.insert_row(
|
||||
'location_property_osmline',
|
||||
place_id=pysql.SQL("nextval('seq_place')"),
|
||||
osm_type=osm_type,
|
||||
osm_id=osm_id or next(idseq),
|
||||
geometry_sector=pysql.Literal(20),
|
||||
partition=pysql.Literal(0),
|
||||
|
||||
@@ -169,8 +169,7 @@ async def test_load_data(dsn, place_row, place_interpolation_row, placex_table,
|
||||
temp_db_cursor, threads):
|
||||
for oid in range(100, 130):
|
||||
place_row(osm_id=oid)
|
||||
place_interpolation_row(osm_type='W', osm_id=342, typ='odd',
|
||||
geom='LINESTRING(0 0, 10 10)')
|
||||
place_interpolation_row(osm_id=342, typ='odd', geom='LINESTRING(0 0, 10 10)')
|
||||
|
||||
temp_db_cursor.execute("""
|
||||
CREATE OR REPLACE FUNCTION placex_insert() RETURNS TRIGGER AS $$
|
||||
|
||||
Reference in New Issue
Block a user