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, tokens INT[])
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 tokens && 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,
151 isin_token INTEGER[])
158 {% for partition in db.partitions %}
159 IF in_partition = {{ partition }} THEN
160 SELECT place_id FROM search_name_{{ partition }}
162 WHERE name_vector && isin_token
163 AND centroid && ST_Expand(point, 0.015)
164 AND address_rank between 26 and 27
165 ORDER BY ST_Distance(centroid, point) ASC limit 1;
170 RAISE EXCEPTION 'Unknown partition %', in_partition;
173 LANGUAGE plpgsql STABLE;
175 CREATE OR REPLACE FUNCTION getNearestNamedPlacePlaceId(in_partition INTEGER,
177 isin_token INTEGER[])
184 {% for partition in db.partitions %}
185 IF in_partition = {{ partition }} THEN
188 FROM search_name_{{ partition }}
189 WHERE name_vector && isin_token
190 AND centroid && ST_Expand(point, 0.04)
191 AND address_rank between 16 and 25
192 ORDER BY ST_Distance(centroid, point) ASC limit 1;
197 RAISE EXCEPTION 'Unknown partition %', in_partition;
200 LANGUAGE plpgsql STABLE;
202 create or replace function insertSearchName(
203 in_partition INTEGER, in_place_id BIGINT, in_name_vector INTEGER[],
204 in_rank_search INTEGER, in_rank_address INTEGER, in_geometry GEOMETRY)
205 RETURNS BOOLEAN AS $$
208 {% for partition in db.partitions %}
209 IF in_partition = {{ partition }} THEN
210 DELETE FROM search_name_{{ partition }} values WHERE place_id = in_place_id;
211 IF in_rank_address > 0 THEN
212 INSERT INTO search_name_{{ partition }} (place_id, address_rank, name_vector, centroid)
213 values (in_place_id, in_rank_address, in_name_vector, in_geometry);
219 RAISE EXCEPTION 'Unknown partition %', in_partition;
225 create or replace function deleteSearchName(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
228 {% for partition in db.partitions %}
229 IF in_partition = {{ partition }} THEN
230 DELETE from search_name_{{ partition }} WHERE place_id = in_place_id;
235 RAISE EXCEPTION 'Unknown partition %', in_partition;
242 create or replace function insertLocationRoad(
243 in_partition INTEGER, in_place_id BIGINT, in_country_code VARCHAR(2), in_geometry GEOMETRY) RETURNS BOOLEAN AS $$
247 {% for partition in db.partitions %}
248 IF in_partition = {{ partition }} THEN
249 DELETE FROM location_road_{{ partition }} where place_id = in_place_id;
250 INSERT INTO location_road_{{ partition }} (partition, place_id, country_code, geometry)
251 values (in_partition, in_place_id, in_country_code, in_geometry);
256 RAISE EXCEPTION 'Unknown partition %', in_partition;
262 create or replace function deleteRoad(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
266 {% for partition in db.partitions %}
267 IF in_partition = {{ partition }} THEN
268 DELETE FROM location_road_{{ partition }} where place_id = in_place_id;
273 RAISE EXCEPTION 'Unknown partition %', in_partition;
280 CREATE OR REPLACE FUNCTION getNearestRoadPlaceId(in_partition INTEGER, point GEOMETRY)
285 search_diameter FLOAT;
288 {% for partition in db.partitions %}
289 IF in_partition = {{ partition }} THEN
290 search_diameter := 0.00005;
291 WHILE search_diameter < 0.1 LOOP
293 SELECT place_id FROM location_road_{{ partition }}
294 WHERE ST_DWithin(geometry, point, search_diameter)
295 ORDER BY ST_Distance(geometry, point) ASC limit 1
299 search_diameter := search_diameter * 2;
305 RAISE EXCEPTION 'Unknown partition %', in_partition;
308 LANGUAGE plpgsql STABLE;
310 CREATE OR REPLACE FUNCTION getNearestParallelRoadFeature(in_partition INTEGER,
316 search_diameter FLOAT;
322 IF ST_GeometryType(line) not in ('ST_LineString') THEN
326 p1 := ST_LineInterpolatePoint(line,0);
327 p2 := ST_LineInterpolatePoint(line,0.5);
328 p3 := ST_LineInterpolatePoint(line,1);
330 {% for partition in db.partitions %}
331 IF in_partition = {{ partition }} THEN
332 search_diameter := 0.0005;
333 WHILE search_diameter < 0.01 LOOP
335 SELECT place_id FROM location_road_{{ partition }}
336 WHERE ST_DWithin(line, geometry, search_diameter)
337 ORDER BY (ST_distance(geometry, p1)+
338 ST_distance(geometry, p2)+
339 ST_distance(geometry, p3)) ASC limit 1
343 search_diameter := search_diameter * 2;
349 RAISE EXCEPTION 'Unknown partition %', in_partition;
352 LANGUAGE plpgsql STABLE;