]> git.openstreetmap.org Git - nominatim.git/blob - sql/partitions.src.sql
df4b3b169338361aee77092a6efaadc9ec5e7d3b
[nominatim.git] / sql / partitions.src.sql
1 drop type nearplace cascade;
2 create type nearplace as (
3   place_id BIGINT
4 );
5
6 drop type nearfeature cascade;
7 create type nearfeature as (
8   place_id BIGINT,
9   keywords int[],
10   rank_address integer,
11   rank_search integer,
12   distance float,
13   isguess boolean
14 );
15
16 CREATE TABLE location_area_country () INHERITS (location_area_large);
17 CREATE INDEX idx_location_area_country_geometry ON location_area_country USING GIST (geometry);
18
19 CREATE TABLE search_name_country () INHERITS (search_name_blank);
20 CREATE INDEX idx_search_name_country_place_id ON search_name_country USING BTREE (place_id);
21 CREATE INDEX idx_search_name_country_name_vector ON search_name_country USING GIN (name_vector) WITH (fastupdate = off);
22
23 -- start
24 CREATE TABLE location_area_large_-partition- () INHERITS (location_area_large);
25 CREATE INDEX idx_location_area_large_-partition-_place_id ON location_area_large_-partition- USING BTREE (place_id);
26 CREATE INDEX idx_location_area_large_-partition-_geometry ON location_area_large_-partition- USING GIST (geometry);
27
28 CREATE TABLE search_name_-partition- () INHERITS (search_name_blank);
29 CREATE INDEX idx_search_name_-partition-_place_id ON search_name_-partition- USING BTREE (place_id);
30 CREATE INDEX idx_search_name_-partition-_centroid ON search_name_-partition- USING GIST (centroid);
31 CREATE INDEX idx_search_name_-partition-_name_vector ON search_name_-partition- USING GIN (name_vector) WITH (fastupdate = off);
32
33 CREATE TABLE location_property_-partition- () INHERITS (location_property);
34 CREATE INDEX idx_location_property_-partition-_place_id ON location_property_-partition- USING BTREE (place_id);
35 CREATE INDEX idx_location_property_-partition-_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id);
36 CREATE INDEX idx_location_property_-partition-_housenumber_parent_place_id ON location_property_-partition- USING BTREE (parent_place_id, housenumber);
37
38 CREATE TABLE location_road_-partition- (
39   partition integer,
40   place_id BIGINT,
41   country_code VARCHAR(2)
42   );
43 SELECT AddGeometryColumn('location_road_-partition-', 'geometry', 4326, 'GEOMETRY', 2);
44 CREATE INDEX idx_location_road_-partition-_geometry ON location_road_-partition- USING GIST (geometry);
45 CREATE INDEX idx_location_road_-partition-_place_id ON location_road_-partition- USING BTREE (place_id);
46
47 -- end
48
49 create or replace function getNearFeatures(in_partition INTEGER, point GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeature AS $$
50 DECLARE
51   r nearfeature%rowtype;
52 BEGIN
53
54 -- start
55   IF in_partition = -partition- THEN
56     FOR r IN 
57       SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(point, centroid)) as distance, isguess FROM (
58         SELECT * FROM location_area_large_-partition- WHERE ST_Contains(geometry, point) and rank_search < maxrank
59         UNION ALL
60         SELECT * FROM location_area_country WHERE ST_Contains(geometry, point) and rank_search < maxrank
61       ) as location_area
62       GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
63       ORDER BY rank_address desc, isin_tokens && keywords desc, isguess asc, 
64         ST_Distance(point, centroid) * 
65           CASE 
66                WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city
67                WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city
68                WHEN rank_address = 16 AND rank_search = 17 THEN 0.5 -- town
69                ELSE 1 END ASC -- everything else
70     LOOP
71       RETURN NEXT r;
72     END LOOP;
73     RETURN;
74   END IF;
75 -- end
76
77   RAISE EXCEPTION 'Unknown partition %', in_partition;
78 END
79 $$
80 LANGUAGE plpgsql;
81
82 create or replace function deleteLocationArea(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
83 DECLARE
84 BEGIN
85
86 -- start
87   IF in_partition = -partition- THEN
88     DELETE from location_area_large_-partition- WHERE place_id = in_place_id;
89     RETURN TRUE;
90   END IF;
91 -- end
92
93   RAISE EXCEPTION 'Unknown partition %', in_partition;
94
95   RETURN FALSE;
96 END
97 $$
98 LANGUAGE plpgsql;
99
100 create or replace function insertLocationAreaLarge(
101   in_partition INTEGER, in_place_id BIGINT, in_country_code VARCHAR(2), in_keywords INTEGER[], 
102   in_rank_search INTEGER, in_rank_address INTEGER, in_estimate BOOLEAN, 
103   in_centroid GEOMETRY, in_geometry GEOMETRY) RETURNS BOOLEAN AS $$
104 DECLARE
105 BEGIN
106
107   IF in_rank_search <= 4 THEN
108     INSERT INTO location_area_country values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
109     RETURN TRUE;
110   END IF;
111
112 -- start
113   IF in_partition = -partition- THEN
114     INSERT INTO location_area_large_-partition- values (in_partition, in_place_id, in_country_code, in_keywords, in_rank_search, in_rank_address, in_estimate, in_centroid, in_geometry);
115     RETURN TRUE;
116   END IF;
117 -- end
118
119   RAISE EXCEPTION 'Unknown partition %', in_partition;
120   RETURN FALSE;
121 END
122 $$
123 LANGUAGE plpgsql;
124
125 create or replace function getNearestNamedFeature(in_partition INTEGER, point GEOMETRY, maxrank INTEGER, isin_token INTEGER) RETURNS setof nearfeature AS $$
126 DECLARE
127   r nearfeature%rowtype;
128 BEGIN
129
130 -- start
131   IF in_partition = -partition- THEN
132     FOR r IN 
133       SELECT place_id, name_vector, address_rank, search_rank,
134           ST_Distance(centroid, point) as distance, null as isguess
135           FROM search_name_-partition-
136           WHERE name_vector @> ARRAY[isin_token]
137           AND search_rank < maxrank
138       UNION ALL
139       SELECT place_id, name_vector, address_rank, search_rank,
140           ST_Distance(centroid, point) as distance, null as isguess
141           FROM search_name_country
142           WHERE name_vector @> ARRAY[isin_token]
143           AND search_rank < maxrank
144       ORDER BY distance ASC limit 1
145     LOOP
146       RETURN NEXT r;
147     END LOOP;
148     RETURN;
149   END IF;
150 -- end
151
152   RAISE EXCEPTION 'Unknown partition %', in_partition;
153 END
154 $$
155 LANGUAGE plpgsql;
156
157 create or replace function getNearestNamedRoadFeature(in_partition INTEGER, point GEOMETRY, isin_token INTEGER) 
158   RETURNS setof nearfeature AS $$
159 DECLARE
160   r nearfeature%rowtype;
161 BEGIN
162
163 -- start
164   IF in_partition = -partition- THEN
165     FOR r IN 
166       SELECT place_id, name_vector, address_rank, search_rank,
167           ST_Distance(centroid, point) as distance, null as isguess
168           FROM search_name_-partition-
169           WHERE name_vector @> ARRAY[isin_token]
170           AND ST_DWithin(centroid, point, 0.01) 
171           AND search_rank between 22 and 27
172       ORDER BY distance ASC limit 1
173     LOOP
174       RETURN NEXT r;
175     END LOOP;
176     RETURN;
177   END IF;
178 -- end
179
180   RAISE EXCEPTION 'Unknown partition %', in_partition;
181 END
182 $$
183 LANGUAGE plpgsql;
184
185 create or replace function getNearestPostcode(in_partition INTEGER, point GEOMETRY) 
186   RETURNS TEXT AS $$
187 DECLARE
188   out_postcode TEXT;
189 BEGIN
190
191 -- start
192   IF in_partition = -partition- THEN
193     SELECT postcode
194         FROM location_area_large_-partition- join placex using (place_id)
195         WHERE st_contains(location_area_large_-partition-.geometry, point)
196         AND class = 'place' and type = 'postcode' 
197       ORDER BY st_distance(location_area_large_-partition-.centroid, point) ASC limit 1
198       INTO out_postcode;
199     RETURN out_postcode;
200   END IF;
201 -- end
202
203   RAISE EXCEPTION 'Unknown partition %', in_partition;
204 END
205 $$
206 LANGUAGE plpgsql;
207
208 create or replace function insertSearchName(
209   in_partition INTEGER, in_place_id BIGINT, in_country_code VARCHAR(2), 
210   in_name_vector INTEGER[], in_nameaddress_vector INTEGER[],
211   in_rank_search INTEGER, in_rank_address INTEGER, in_importance FLOAT,
212   in_centroid GEOMETRY) RETURNS BOOLEAN AS $$
213 DECLARE
214 BEGIN
215
216   DELETE FROM search_name WHERE place_id = in_place_id;
217   INSERT INTO search_name values (in_place_id, in_rank_search, in_rank_address, in_importance, in_country_code, 
218     in_name_vector, in_nameaddress_vector, in_centroid);
219
220   IF in_rank_search <= 4 THEN
221     DELETE FROM search_name_country WHERE place_id = in_place_id;
222     INSERT INTO search_name_country values (in_place_id, in_rank_search, in_rank_address, in_importance, in_country_code, 
223       in_name_vector, in_nameaddress_vector, in_centroid);
224     RETURN TRUE;
225   END IF;
226
227 -- start
228   IF in_partition = -partition- THEN
229     DELETE FROM search_name_-partition- values WHERE place_id = in_place_id;
230     INSERT INTO search_name_-partition- values (in_place_id, in_rank_search, in_rank_address, 0, in_country_code, 
231       in_name_vector, in_nameaddress_vector, in_centroid);
232     RETURN TRUE;
233   END IF;
234 -- end
235
236   RAISE EXCEPTION 'Unknown partition %', in_partition;
237   RETURN FALSE;
238 END
239 $$
240 LANGUAGE plpgsql;
241
242 create or replace function deleteSearchName(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
243 DECLARE
244 BEGIN
245
246   DELETE from search_name WHERE place_id = in_place_id;
247   DELETE from search_name_country WHERE place_id = in_place_id;
248
249 -- start
250   IF in_partition = -partition- THEN
251     DELETE from search_name_-partition- WHERE place_id = in_place_id;
252     RETURN TRUE;
253   END IF;
254 -- end
255
256   RAISE EXCEPTION 'Unknown partition %', in_partition;
257
258   RETURN FALSE;
259 END
260 $$
261 LANGUAGE plpgsql;
262
263 create or replace function insertLocationRoad(
264   in_partition INTEGER, in_place_id BIGINT, in_country_code VARCHAR(2), in_geometry GEOMETRY) RETURNS BOOLEAN AS $$
265 DECLARE
266 BEGIN
267
268 -- start
269   IF in_partition = -partition- THEN
270     DELETE FROM location_road_-partition- where place_id = in_place_id;
271     INSERT INTO location_road_-partition- values (in_partition, in_place_id, in_country_code, in_geometry);
272     RETURN TRUE;
273   END IF;
274 -- end
275
276   RAISE EXCEPTION 'Unknown partition %', in_partition;
277   RETURN FALSE;
278 END
279 $$
280 LANGUAGE plpgsql;
281
282 create or replace function deleteRoad(in_partition INTEGER, in_place_id BIGINT) RETURNS BOOLEAN AS $$
283 DECLARE
284 BEGIN
285
286 -- start
287   IF in_partition = -partition- THEN
288     DELETE FROM location_road_-partition- where place_id = in_place_id;
289     RETURN TRUE;
290   END IF;
291 -- end
292
293   RAISE EXCEPTION 'Unknown partition %', in_partition;
294
295   RETURN FALSE;
296 END
297 $$
298 LANGUAGE plpgsql;
299
300 create or replace function getNearestRoadFeature(in_partition INTEGER, point GEOMETRY) RETURNS setof nearfeature AS $$
301 DECLARE
302   r nearfeature%rowtype;
303   search_diameter FLOAT;  
304 BEGIN
305
306 -- start
307   IF in_partition = -partition- THEN
308     search_diameter := 0.00005;
309     WHILE search_diameter < 0.1 LOOP
310       FOR r IN 
311         SELECT place_id, null, null, null,
312             ST_Distance(geometry, point) as distance, null as isguess
313             FROM location_road_-partition-
314             WHERE ST_DWithin(geometry, point, search_diameter) 
315         ORDER BY distance ASC limit 1
316       LOOP
317         RETURN NEXT r;
318         RETURN;
319       END LOOP;
320       search_diameter := search_diameter * 2;
321     END LOOP;
322     RETURN;
323   END IF;
324 -- end
325
326   RAISE EXCEPTION 'Unknown partition %', in_partition;
327 END
328 $$
329 LANGUAGE plpgsql;
330
331 create or replace function getNearestParellelRoadFeature(in_partition INTEGER, line GEOMETRY) RETURNS setof nearfeature AS $$
332 DECLARE
333   r nearfeature%rowtype;
334   search_diameter FLOAT;  
335   p1 GEOMETRY;
336   p2 GEOMETRY;
337   p3 GEOMETRY;
338 BEGIN
339
340   IF st_geometrytype(line) not in ('ST_LineString') THEN
341     RETURN;
342   END IF;
343
344   p1 := ST_Line_Interpolate_Point(line,0);
345   p2 := ST_Line_Interpolate_Point(line,0.5);
346   p3 := ST_Line_Interpolate_Point(line,1);
347
348 -- start
349   IF in_partition = -partition- THEN
350     search_diameter := 0.0005;
351     WHILE search_diameter < 0.01 LOOP
352       FOR r IN 
353         SELECT place_id, null, null, null,
354             ST_Distance(geometry, line) as distance, null as isguess
355             FROM location_road_-partition-
356             WHERE ST_DWithin(line, geometry, search_diameter)
357             ORDER BY (ST_distance(geometry, p1)+
358                       ST_distance(geometry, p2)+
359                       ST_distance(geometry, p3)) ASC limit 1
360       LOOP
361         RETURN NEXT r;
362         RETURN;
363       END LOOP;
364       search_diameter := search_diameter * 2;
365     END LOOP;
366     RETURN;
367   END IF;
368 -- end
369
370   RAISE EXCEPTION 'Unknown partition %', in_partition;
371 END
372 $$
373 LANGUAGE plpgsql;