]> git.openstreetmap.org Git - nominatim.git/blob - lib-sql/tokenizer/icu_tokenizer.sql
Merge pull request #2452 from lonvia/update-houses-on-street-name-change
[nominatim.git] / lib-sql / tokenizer / icu_tokenizer.sql
1 -- Get tokens used for searching the given place.
2 --
3 -- These are the tokens that will be saved in the search_name table.
4 CREATE OR REPLACE FUNCTION token_get_name_search_tokens(info JSONB)
5   RETURNS INTEGER[]
6 AS $$
7   SELECT (info->>'names')::INTEGER[]
8 $$ LANGUAGE SQL IMMUTABLE STRICT;
9
10
11 -- Get tokens for matching the place name against others.
12 --
13 -- This should usually be restricted to full name tokens.
14 CREATE OR REPLACE FUNCTION token_get_name_match_tokens(info JSONB)
15   RETURNS INTEGER[]
16 AS $$
17   SELECT (info->>'names')::INTEGER[]
18 $$ LANGUAGE SQL IMMUTABLE STRICT;
19
20
21 -- Return the housenumber tokens applicable for the place.
22 CREATE OR REPLACE FUNCTION token_get_housenumber_search_tokens(info JSONB)
23   RETURNS INTEGER[]
24 AS $$
25   SELECT (info->>'hnr_tokens')::INTEGER[]
26 $$ LANGUAGE SQL IMMUTABLE STRICT;
27
28
29 -- Return the housenumber in the form that it can be matched during search.
30 CREATE OR REPLACE FUNCTION token_normalized_housenumber(info JSONB)
31   RETURNS TEXT
32 AS $$
33   SELECT info->>'hnr';
34 $$ LANGUAGE SQL IMMUTABLE STRICT;
35
36
37 CREATE OR REPLACE FUNCTION token_addr_street_match_tokens(info JSONB)
38   RETURNS INTEGER[]
39 AS $$
40   SELECT (info->>'street')::INTEGER[]
41 $$ LANGUAGE SQL IMMUTABLE STRICT;
42
43
44 CREATE OR REPLACE FUNCTION token_addr_place_match_tokens(info JSONB)
45   RETURNS INTEGER[]
46 AS $$
47   SELECT (info->>'place_match')::INTEGER[]
48 $$ LANGUAGE SQL IMMUTABLE STRICT;
49
50
51 CREATE OR REPLACE FUNCTION token_addr_place_search_tokens(info JSONB)
52   RETURNS INTEGER[]
53 AS $$
54   SELECT (info->>'place_search')::INTEGER[]
55 $$ LANGUAGE SQL IMMUTABLE STRICT;
56
57
58 DROP TYPE IF EXISTS token_addresstoken CASCADE;
59 CREATE TYPE token_addresstoken AS (
60   key TEXT,
61   match_tokens INT[],
62   search_tokens INT[]
63 );
64
65 CREATE OR REPLACE FUNCTION token_get_address_tokens(info JSONB)
66   RETURNS SETOF token_addresstoken
67 AS $$
68   SELECT key, (value->>1)::int[] as match_tokens,
69          (value->>0)::int[] as search_tokens
70   FROM jsonb_each(info->'addr');
71 $$ LANGUAGE SQL IMMUTABLE STRICT;
72
73
74 CREATE OR REPLACE FUNCTION token_normalized_postcode(postcode TEXT)
75   RETURNS TEXT
76 AS $$
77   SELECT CASE WHEN postcode SIMILAR TO '%(,|;)%' THEN NULL ELSE upper(trim(postcode))END;
78 $$ LANGUAGE SQL IMMUTABLE STRICT;
79
80
81 -- Return token info that should be saved permanently in the database.
82 CREATE OR REPLACE FUNCTION token_strip_info(info JSONB)
83   RETURNS JSONB
84 AS $$
85   SELECT NULL::JSONB;
86 $$ LANGUAGE SQL IMMUTABLE STRICT;
87
88 --------------- private functions ----------------------------------------------
89
90 CREATE OR REPLACE FUNCTION getorcreate_full_word(norm_term TEXT, lookup_terms TEXT[],
91                                                  OUT full_token INT,
92                                                  OUT partial_tokens INT[])
93   AS $$
94 DECLARE
95   partial_terms TEXT[] = '{}'::TEXT[];
96   term TEXT;
97   term_id INTEGER;
98   term_count INTEGER;
99 BEGIN
100   SELECT min(word_id) INTO full_token
101     FROM word WHERE word = norm_term and type = 'W';
102
103   IF full_token IS NULL THEN
104     full_token := nextval('seq_word');
105     INSERT INTO word (word_id, word_token, type, word, info)
106       SELECT full_token, lookup_term, 'W', norm_term,
107              json_build_object('count', 0)
108         FROM unnest(lookup_terms) as lookup_term;
109   END IF;
110
111   FOR term IN SELECT unnest(string_to_array(unnest(lookup_terms), ' ')) LOOP
112     term := trim(term);
113     IF NOT (ARRAY[term] <@ partial_terms) THEN
114       partial_terms := partial_terms || term;
115     END IF;
116   END LOOP;
117
118   partial_tokens := '{}'::INT[];
119   FOR term IN SELECT unnest(partial_terms) LOOP
120     SELECT min(word_id), max(info->>'count') INTO term_id, term_count
121       FROM word WHERE word_token = term and type = 'w';
122
123     IF term_id IS NULL THEN
124       term_id := nextval('seq_word');
125       term_count := 0;
126       INSERT INTO word (word_id, word_token, type, info)
127         VALUES (term_id, term, 'w', json_build_object('count', term_count));
128     END IF;
129
130     IF term_count < {{ max_word_freq }} THEN
131       partial_tokens := array_merge(partial_tokens, ARRAY[term_id]);
132     END IF;
133   END LOOP;
134 END;
135 $$
136 LANGUAGE plpgsql;
137
138
139 CREATE OR REPLACE FUNCTION getorcreate_hnr_id(lookup_term TEXT)
140   RETURNS INTEGER
141   AS $$
142 DECLARE
143   return_id INTEGER;
144 BEGIN
145   SELECT min(word_id) INTO return_id FROM word
146     WHERE word_token = lookup_term and type = 'H';
147
148   IF return_id IS NULL THEN
149     return_id := nextval('seq_word');
150     INSERT INTO word (word_id, word_token, type)
151       VALUES (return_id, lookup_term, 'H');
152   END IF;
153
154   RETURN return_id;
155 END;
156 $$
157 LANGUAGE plpgsql;