1 DROP TYPE IF EXISTS nearfeaturecentr CASCADE;
2 CREATE TYPE nearfeaturecentr AS (
13 -- feature intersects geoemtry
14 -- for areas and linestrings they must touch at least along a line
15 CREATE OR REPLACE FUNCTION is_relevant_geometry(de9im TEXT, geom_type TEXT)
19 IF substring(de9im from 1 for 2) != 'FF' THEN
23 IF geom_type = 'ST_Point' THEN
24 RETURN substring(de9im from 4 for 1) = '0';
27 IF geom_type in ('ST_LineString', 'ST_MultiLineString') THEN
28 RETURN substring(de9im from 4 for 1) = '1';
31 RETURN substring(de9im from 4 for 1) = '2';
33 $$ LANGUAGE plpgsql IMMUTABLE;
35 create or replace function getNearFeatures(in_partition INTEGER, feature GEOMETRY, maxrank INTEGER) RETURNS setof nearfeaturecentr AS $$
37 r nearfeaturecentr%rowtype;
40 {% for partition in db.partitions %}
41 IF in_partition = {{ partition }} THEN
43 SELECT place_id, keywords, rank_address, rank_search,
44 min(ST_Distance(feature, centroid)) as distance,
45 isguess, postcode, centroid
46 FROM location_area_large_{{ partition }}
47 WHERE geometry && feature
48 AND is_relevant_geometry(ST_Relate(geometry, feature), ST_GeometryType(feature))
49 AND rank_address < maxrank
50 -- Postcodes currently still use rank_search to define for which
51 -- features they are relevant.
52 AND not (rank_address in (5, 11) and rank_search > maxrank)
53 GROUP BY place_id, keywords, rank_address, rank_search, isguess, postcode, centroid
61 RAISE EXCEPTION 'Unknown partition %', in_partition;
64 LANGUAGE plpgsql STABLE;
67 CREATE OR REPLACE FUNCTION get_address_place(in_partition SMALLINT, feature GEOMETRY,
68 from_rank SMALLINT, to_rank SMALLINT,
69 extent FLOAT, token_info JSONB, key TEXT)
70 RETURNS nearfeaturecentr
73 r nearfeaturecentr%rowtype;
75 {% for partition in db.partitions %}
76 IF in_partition = {{ partition }} THEN
77 SELECT place_id, keywords, rank_address, rank_search,
78 min(ST_Distance(feature, centroid)) as distance,
79 isguess, postcode, centroid INTO r
80 FROM location_area_large_{{ partition }}
81 WHERE geometry && ST_Expand(feature, extent)
82 AND rank_address between from_rank and to_rank
83 AND token_matches_address(token_info, key, keywords)
84 GROUP BY place_id, keywords, rank_address, rank_search, isguess, postcode, centroid
85 ORDER BY bool_or(ST_Intersects(geometry, feature)), distance LIMIT 1;
90 RAISE EXCEPTION 'Unknown partition %', in_partition;
93 LANGUAGE plpgsql STABLE;
96 create or replace function deleteLocationArea(in_partition INTEGER, in_place_id BIGINT, in_rank_search INTEGER) RETURNS BOOLEAN AS $$
100 IF in_rank_search <= 4 THEN
101 DELETE from location_area_country WHERE place_id = in_place_id;
105 {% for partition in db.partitions %}
106 IF in_partition = {{ partition }} THEN
107 DELETE from location_area_large_{{ partition }} WHERE place_id = in_place_id;
112 RAISE EXCEPTION 'Unknown partition %', in_partition;
119 create or replace function insertLocationAreaLarge(
120 in_partition INTEGER, in_place_id BIGINT, in_country_code VARCHAR(2), in_keywords INTEGER[],
121 in_rank_search INTEGER, in_rank_address INTEGER, in_estimate BOOLEAN, postcode TEXT,
122 in_centroid GEOMETRY, in_geometry GEOMETRY) RETURNS BOOLEAN AS $$
125 IF in_rank_address = 0 THEN
129 IF in_rank_search <= 4 and not in_estimate THEN
130 INSERT INTO location_area_country (place_id, country_code, geometry)
131 values (in_place_id, in_country_code, in_geometry);
135 {% for partition in db.partitions %}
136 IF in_partition = {{ partition }} THEN
137 INSERT INTO location_area_large_{{ partition }} (partition, place_id, country_code, keywords, rank_search, rank_address, isguess, postcode, centroid, geometry)
138 values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, postcode, in_centroid, in_geometry);
143 RAISE EXCEPTION 'Unknown partition %', in_partition;
149 CREATE OR REPLACE FUNCTION getNearestNamedRoadPlaceId(in_partition INTEGER,
157 IF not token_has_addr_street(token_info) THEN
161 {% for partition in db.partitions %}
162 IF in_partition = {{ partition }} THEN
163 SELECT place_id FROM search_name_{{ partition }}
165 WHERE token_matches_street(token_info, name_vector)
166 AND centroid && ST_Expand(point, 0.015)
167 AND address_rank between 26 and 27
168 ORDER BY ST_Distance(centroid, point) ASC limit 1;
173 RAISE EXCEPTION 'Unknown partition %', in_partition;
176 LANGUAGE plpgsql STABLE;
178 CREATE OR REPLACE FUNCTION getNearestNamedPlacePlaceId(in_partition INTEGER,
186 IF not token_has_addr_place(token_info) THEN
190 {% for partition in db.partitions %}
191 IF in_partition = {{ partition }} THEN
194 FROM search_name_{{ partition }}
195 WHERE token_matches_place(token_info, name_vector)
196 AND centroid && ST_Expand(point, 0.04)
197 AND address_rank between 16 and 25
198 ORDER BY ST_Distance(centroid, point) ASC limit 1;
203 RAISE EXCEPTION 'Unknown partition %', in_partition;
206 LANGUAGE plpgsql STABLE;
208 create or replace function insertSearchName(
209 in_partition INTEGER, in_place_id BIGINT, in_name_vector INTEGER[],
210 in_rank_search INTEGER, in_rank_address INTEGER, in_geometry GEOMETRY)
211 RETURNS BOOLEAN AS $$
214 {% for partition in db.partitions %}
215 IF in_partition = {{ partition }} THEN
216 DELETE FROM search_name_{{ partition }} values WHERE place_id = in_place_id;
217 IF in_rank_address > 0 THEN
218 INSERT INTO search_name_{{ partition }} (place_id, address_rank, name_vector, centroid)
219 values (in_place_id, in_rank_address, in_name_vector, in_geometry);
225 RAISE EXCEPTION 'Unknown partition %', in_partition;
231 create or replace function deleteSearchName(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
234 {% for partition in db.partitions %}
235 IF in_partition = {{ partition }} THEN
236 DELETE from search_name_{{ partition }} WHERE place_id = in_place_id;
241 RAISE EXCEPTION 'Unknown partition %', in_partition;
248 create or replace function insertLocationRoad(
249 in_partition INTEGER, in_place_id BIGINT, in_country_code VARCHAR(2), in_geometry GEOMETRY) RETURNS BOOLEAN AS $$
253 {% for partition in db.partitions %}
254 IF in_partition = {{ partition }} THEN
255 DELETE FROM location_road_{{ partition }} where place_id = in_place_id;
256 INSERT INTO location_road_{{ partition }} (partition, place_id, country_code, geometry)
257 values (in_partition, in_place_id, in_country_code, in_geometry);
262 RAISE EXCEPTION 'Unknown partition %', in_partition;
268 create or replace function deleteRoad(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
272 {% for partition in db.partitions %}
273 IF in_partition = {{ partition }} THEN
274 DELETE FROM location_road_{{ partition }} where place_id = in_place_id;
279 RAISE EXCEPTION 'Unknown partition %', in_partition;
286 CREATE OR REPLACE FUNCTION getNearestRoadPlaceId(in_partition INTEGER, point GEOMETRY)
291 search_diameter FLOAT;
294 {% for partition in db.partitions %}
295 IF in_partition = {{ partition }} THEN
296 search_diameter := 0.00005;
297 WHILE search_diameter < 0.1 LOOP
299 SELECT place_id FROM location_road_{{ partition }}
300 WHERE ST_DWithin(geometry, point, search_diameter)
301 ORDER BY ST_Distance(geometry, point) ASC limit 1
305 search_diameter := search_diameter * 2;
311 RAISE EXCEPTION 'Unknown partition %', in_partition;
314 LANGUAGE plpgsql STABLE;
316 CREATE OR REPLACE FUNCTION getNearestParallelRoadFeature(in_partition INTEGER,
322 search_diameter FLOAT;
328 IF ST_GeometryType(line) not in ('ST_LineString') THEN
332 p1 := ST_LineInterpolatePoint(line,0);
333 p2 := ST_LineInterpolatePoint(line,0.5);
334 p3 := ST_LineInterpolatePoint(line,1);
336 {% for partition in db.partitions %}
337 IF in_partition = {{ partition }} THEN
338 search_diameter := 0.0005;
339 WHILE search_diameter < 0.01 LOOP
341 SELECT place_id FROM location_road_{{ partition }}
342 WHERE ST_DWithin(line, geometry, search_diameter)
343 ORDER BY (ST_distance(geometry, p1)+
344 ST_distance(geometry, p2)+
345 ST_distance(geometry, p3)) ASC limit 1
349 search_diameter := search_diameter * 2;
355 RAISE EXCEPTION 'Unknown partition %', in_partition;
358 LANGUAGE plpgsql STABLE;