diff --git a/lib-lua/themes/nominatim/init.lua b/lib-lua/themes/nominatim/init.lua index fd15968b..173b9f25 100644 --- a/lib-lua/themes/nominatim/init.lua +++ b/lib-lua/themes/nominatim/init.lua @@ -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 diff --git a/lib-sql/functions/interpolation.sql b/lib-sql/functions/interpolation.sql index d558378d..8a9fc2df 100644 --- a/lib-sql/functions/interpolation.sql +++ b/lib-sql/functions/interpolation.sql @@ -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; diff --git a/lib-sql/functions/placex_triggers.sql b/lib-sql/functions/placex_triggers.sql index 00868589..19764ed9 100644 --- a/lib-sql/functions/placex_triggers.sql +++ b/lib-sql/functions/placex_triggers.sql @@ -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; diff --git a/lib-sql/functions/utils.sql b/lib-sql/functions/utils.sql index 878301a0..f1788bcb 100644 --- a/lib-sql/functions/utils.sql +++ b/lib-sql/functions/utils.sql @@ -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; diff --git a/lib-sql/indices.sql b/lib-sql/indices.sql index f3b79705..f350f951 100644 --- a/lib-sql/indices.sql +++ b/lib-sql/indices.sql @@ -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 ); --- diff --git a/lib-sql/tables/interpolation.sql b/lib-sql/tables/interpolation.sql index a7b53209..1a4d72af 100644 --- a/lib-sql/tables/interpolation.sql +++ b/lib-sql/tables/interpolation.sql @@ -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, diff --git a/src/nominatim_db/tools/database_import.py b/src/nominatim_db/tools/database_import.py index 388cca0f..4bf9c406 100644 --- a/src/nominatim_db/tools/database_import.py +++ b/src/nominatim_db/tools/database_import.py @@ -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) diff --git a/test/bdd/features/db/import/interpolation.feature b/test/bdd/features/db/import/interpolation.feature index cc332852..764a062e 100644 --- a/test/bdd/features/db/import/interpolation.feature +++ b/test/bdd/features/db/import/interpolation.feature @@ -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 | diff --git a/test/bdd/features/db/query/housenumbers.feature b/test/bdd/features/db/query/housenumbers.feature index df466ecb..8e1b1e5d 100644 --- a/test/bdd/features/db/query/housenumbers.feature +++ b/test/bdd/features/db/query/housenumbers.feature @@ -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 | diff --git a/test/bdd/features/osm2pgsql/import/interpolation.feature b/test/bdd/features/osm2pgsql/import/interpolation.feature index ce4349bc..07e53685 100644 --- a/test/bdd/features/osm2pgsql/import/interpolation.feature +++ b/test/bdd/features/osm2pgsql/import/interpolation.feature @@ -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" | diff --git a/test/bdd/features/osm2pgsql/update/interpolations.feature b/test/bdd/features/osm2pgsql/update/interpolations.feature index 6c76c91b..b0936d2c 100644 --- a/test/bdd/features/osm2pgsql/update/interpolations.feature +++ b/test/bdd/features/osm2pgsql/update/interpolations.feature @@ -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 | diff --git a/test/bdd/features/osm2pgsql/update/postcodes.feature b/test/bdd/features/osm2pgsql/update/postcodes.feature index 3ae73f27..dd462d1c 100644 --- a/test/bdd/features/osm2pgsql/update/postcodes.feature +++ b/test/bdd/features/osm2pgsql/update/postcodes.feature @@ -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 diff --git a/test/bdd/test_db.py b/test/bdd/test_db.py index 91b5b922..47a99578 100644 --- a/test/bdd/test_db.py +++ b/test/bdd/test_db.py @@ -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', diff --git a/test/python/conftest.py b/test/python/conftest.py index 9617be5a..fbfda1de 100644 --- a/test/python/conftest.py +++ b/test/python/conftest.py @@ -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), diff --git a/test/python/tools/test_database_import.py b/test/python/tools/test_database_import.py index 274fd529..3e98b575 100644 --- a/test/python/tools/test_database_import.py +++ b/test/python/tools/test_database_import.py @@ -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 $$