WordPress.org

Make WordPress Core

Ticket #15652: public.string.sql

File public.string.sql, 4.1 KB (added by Denis-de-Bernardy, 3 years ago)
Line 
1/**
2 * @param varchar _str The input string.
3 * @return varchar The unaccented string.
4 */
5CREATE OR REPLACE FUNCTION public.unaccent(varchar)
6        RETURNS varchar
7AS $$
8DECLARE
9        _str    varchar := $1;
10        _find   constant varchar :=     'ÀÁÂÃÄÅĀĄĂÆÈÉÊËĒĘĚĔĖÐÌÍÎÏĪĨĬĮİIJÒÓÔÕÖØŌŐŎŒÙÚÛÜŪŮŰŬŨŲÝŶŸ' ||
11                                                                'àáâãäåāąăæèéêëēęěĕėðìíîïīĩĭįıijòóôõöøōőŏœùúûüūůűŭũųýÿŷ' ||
12                                                                'ÇĆČĈĊĎĐƑĜĞĠĢĤĦĴĶŁĽĹĻĿÑŃŇŅŊŔŘŖŚŠŞŜȘſŤŢŦȚÞŴŹŽŻ' ||
13                                                                'çćčĉċďđƒĝğġģĥħĵĸķłľĺļŀñńňņʼnŋŕřŗśšşŝșßťţŧțþŵžżź';
14        _repl   constant varchar :=     'AAAAAAAAAAEEEEEEEEEEIIIIIIIIIIOOOOOOOOOOUUUUUUUUUUYYY' ||
15                                                                'aaaaaaaaaaeeeeeeeeeeiiiiiiiiiioooooooooouuuuuuuuuuyyy' ||
16                                                                'CCCCCDDFGGGGHHJKLLLLLNNNNNRRRSSSSSSTTTTTWZZZ' ||
17                                                                'cccccddfgggghhjkklllllnnnnnnrrrsssssstttttwzzz';
18BEGIN
19        -- Bail if the string is empty
20        IF      _str = ''
21        THEN
22                RETURN _str;
23        END IF;
24       
25        -- Common expansions
26        _str := replace(_str, 'ſ', 'SS');
27        _str := replace(_str, 'ß', 'ss');
28        _str := replace(_str, 'Å', 'AA');
29        _str := replace(_str, 'å', 'aa');
30        _str := replace(_str, 'IJ', 'IJ');
31        _str := replace(_str, 'ij', 'ij');
32        _str := regexp_replace(_str, '([ÄÆÖŒÜ])', E'\\1E', 'g');
33        _str := regexp_replace(_str, '([äæöü])', E'\\1e', 'g');
34       
35        -- Translate what's left
36        _str := translate(_str, _find, _repl);
37       
38        RETURN _str;
39END;
40$$ IMMUTABLE STRICT LANGUAGE plpgsql COST 1;
41
42COMMENT ON FUNCTION public.unaccent(varchar) IS
43'Strips accents from a string. Useful if the built-in unaccent() won''t
44compile properly, as is the case for the one from macports...';
45
46/**
47 * @param varchar _str The input string.
48 * @param char _sep The separator.
49 * @return varchar The output slug.
50 */
51CREATE OR REPLACE FUNCTION public.to_slug(varchar, varchar = '-')
52        RETURNS varchar
53AS $$
54DECLARE
55        _str            varchar := $1;
56        _sep            constant varchar(1) := $2;
57BEGIN
58        -- Bail if the string is empty
59        IF      _str = ''
60        THEN
61                RETURN _str;
62        END IF;
63       
64        -- Strip accents and lower the case
65        _str := lower(public.unaccent(_str));
66       
67        -- Replace nonsensical characters
68        _str := regexp_replace(_str, '[^a-z0-9]+', _sep, 'g');
69       
70        -- Trim the result
71        _str := trim(both _sep from _str);
72       
73        RETURN _str;
74END;
75$$ IMMUTABLE STRICT LANGUAGE plpgsql COST 1;
76
77COMMENT ON FUNCTION public.to_slug(varchar, varchar) IS
78'"Slugifies" a string, e.g. turns A1@bC! into a1-bc for use as slugs.';
79
80/**
81 * @param varchar The input string.
82 * @return varchar The output string for consumption in natural sorting.
83 */
84CREATE OR REPLACE FUNCTION public.natsort(varchar)
85        RETURNS varchar
86AS $$
87DECLARE
88        _str    varchar := $1;
89        _pad    int             := 15; -- Maximum precision for PostgreSQL floats
90BEGIN
91        -- Bail if the string is empty
92        IF      trim(_str) = ''
93        THEN
94                RETURN '';
95        END IF;
96       
97        -- Strip accents and lower the case
98        _str := lower(public.unaccent(_str));
99       
100        -- Replace nonsensical characters
101        _str := regexp_replace(_str, E'[^a-z0-9$¢£¥₤€@&%\\(\\)\\[\\]\\{\\}_:;,\\.\\?!\\+\\-]+', ' ', 'g');
102       
103        -- Trim the result
104        _str := trim(_str);
105       
106        -- We're done if the string contains no numbers
107        IF      _str !~ '[0-9]'
108        THEN
109                RETURN _str;
110        END IF;
111       
112        -- Force spaces between numbers, so we can use regexp_split_to_table()
113        _str := regexp_replace(_str, E'((?:[0-9]+|[0-9]*\\.[0-9]+)(?:e[+-]?[0-9]+\\M)?)', E' \\1 ', 'g');
114       
115        -- Pad zeros to obtain a reasonably natural looking sort order
116        RETURN array_to_string(ARRAY (
117        SELECT  CASE
118                        WHEN val !~ E'^\\.?[0-9]' THEN
119                                -- Not a number; return as is
120                                val
121                        ELSE
122                                -- Do our best...
123                                COALESCE(lpad(substring(val::numeric::text from '^[0-9]+'), _pad, '0'), '') ||
124                                COALESCE(rpad(substring(val::numeric::text from E'\\.[0-9]+'), _pad, '0'), '')
125                        END
126        FROM    regexp_split_to_table(_str, E'\\s+') as val
127        WHERE   val <> ''
128        ), ' ');
129END;
130$$ IMMUTABLE STRICT LANGUAGE plpgsql COST 1;
131
132COMMENT ON FUNCTION public.natsort(varchar) IS
133'Rewrites a string so it can be used in natural sorting.
134
135It''s by no means bullet proof, but it works for reasonably small positive
136numbers, and it''s fast enough to be used in a trigger or an index.';