-
Notifications
You must be signed in to change notification settings - Fork 136
/
zzz_language.sql
164 lines (151 loc) · 4.71 KB
/
zzz_language.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
-- Given an hstore, delete all entries that have empty values
CREATE OR REPLACE FUNCTION delete_empty_keys(tags hstore) RETURNS hstore AS
$$
SELECT hstore(array_agg(key), array_agg(value))
FROM
each(hstore(tags))
WHERE value != '';
$$ LANGUAGE sql IMMUTABLE
STRICT
PARALLEL SAFE;
CREATE OR REPLACE FUNCTION remove_latin(text) RETURNS text AS $$
DECLARE
i integer;
DECLARE
letter text;
result text = '';
BEGIN
FOR i IN 1..char_length($1) LOOP
letter := substr($1, i, 1);
IF (unaccent(letter) !~ '^[a-zA-Z].*') THEN
result := result || letter;
END IF;
END LOOP;
result := regexp_replace(result, '(\([ -.]*\)|\[[ -.]*\])', '');
result := regexp_replace(result, '\s+', ' ', 'g');
result := regexp_replace(result, ' +\. *$', '');
result := regexp_replace(result, '^ ?\. ', '');
result := regexp_replace(result, '^(\/ \/)+', ' ', 'g');
result := regexp_replace(result, '^( \/)+', '/','g');
result := trim(both ' -\n' from result);
RETURN result;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;
-- See osml10n_is_latin
-- https://github.com/openmaptiles/mapnik-german-l10n/blob/ea5da9cdfa6c931ae73eac747849140547ecd321/plpgsql/get_localized_name.sql#L19
CREATE or REPLACE FUNCTION omt_is_latin(text) RETURNS BOOLEAN AS $$
DECLARE
i integer;
ascii_val int;
BEGIN
FOR i IN 1..char_length($1) LOOP
ascii_val := ascii(substr($1, i, 1));
IF (ascii_val > 591
-- Vietnam
-- https://en.wikipedia.org/wiki/Latin_script_in_Unicode
-- https://en.wikipedia.org/wiki/Latin_Extended_Additional
AND ascii_val NOT BETWEEN x'1E00'::int AND x'1EFF'::int
-- https://en.wikipedia.org/wiki/Combining_character
AND ascii_val NOT BETWEEN x'0300'::int AND x'036F'::int
-- Azerbaijan
-- https://en.wikipedia.org/wiki/IPA_Extensions
AND ascii_val <> x'0259'::int
) THEN
RETURN false;
END IF;
END LOOP;
RETURN true;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;
CREATE OR REPLACE FUNCTION get_latin_name(tags hstore, geometry geometry) RETURNS text AS $$
SELECT COALESCE(
CASE
WHEN tags->'name' is not null and omt_is_latin(tags->'name')
THEN tags->'name'
END,
NULLIF(tags->'name:en', ''),
NULLIF(tags->'int_name', ''),
NULLIF(osml10n_get_name_without_brackets_from_tags(tags, 'en', geometry), '')
);
$$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION get_nonlatin_name(tags hstore) RETURNS text AS $$
SELECT
CASE
WHEN tags->'name' is not null and omt_is_latin(tags->'name')
THEN NULL
WHEN unaccent(tags->'name') ~ '[a-zA-Z]'
THEN remove_latin(tags->'name')
ELSE tags->'name'
END;
$$ LANGUAGE SQL IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION get_basic_names(tags hstore, geometry geometry) RETURNS hstore AS $$
DECLARE
tags_array text[] := ARRAY[]::text[];
name_latin text;
name_nonlatin text;
name_int text;
BEGIN
name_latin := get_latin_name(tags, geometry);
name_nonlatin := get_nonlatin_name(tags);
IF (name_nonlatin = name_latin) THEN
name_nonlatin := null;
END IF;
name_int := COALESCE(
NULLIF(tags->'int_name', ''),
NULLIF(tags->'name:en', ''),
NULLIF(name_latin, ''),
tags->'name'
);
IF name_latin IS NOT NULL THEN
tags_array := tags_array || ARRAY['name:latin', name_latin];
END IF;
IF name_nonlatin IS NOT NULL THEN
tags_array := tags_array || ARRAY['name:nonlatin', name_nonlatin];
END IF;
IF name_int IS NOT NULL THEN
tags_array := tags_array || ARRAY['name_int', name_int];
END IF;
RETURN hstore(tags_array);
END;
$$
LANGUAGE plpgsql IMMUTABLE;
-- The wd_names table may also be created by the import-wikidata
-- Make sure the SQL table structure is in sync.
CREATE TABLE IF NOT EXISTS wd_names(
id varchar(20) CONSTRAINT id_key PRIMARY KEY,
labels hstore
);
CREATE OR REPLACE FUNCTION merge_wiki_names(tags hstore) RETURNS hstore AS $$
DECLARE
result hstore;
BEGIN
IF tags ? 'wikidata' THEN
select INTO result
CASE
WHEN avals(wd.labels) && avals(tags)
THEN slice_language_tags(wd.labels) || tags
ELSE tags
END
FROM wd_names wd
WHERE wd.id = tags->'wikidata';
IF result IS NULL THEN
result := tags;
END IF;
ELSE
result := tags;
END IF;
RETURN result;
END;
$$ STRICT
LANGUAGE plpgsql IMMUTABLE;
CREATE OR REPLACE FUNCTION update_tags(tags hstore, geometry
geometry) RETURNS hstore AS $$
DECLARE
result hstore;
BEGIN
result := delete_empty_keys(tags) || get_basic_names(tags, geometry);
result := merge_wiki_names(result);
RETURN result;
END;
$$ LANGUAGE plpgsql IMMUTABLE
STRICT;