Функция shorten

Напишем более универсальную функцию: это не потребует усложнения кода, и позволит обойтись без "магических констант".

=> CREATE OR REPLACE FUNCTION shorten(s text, max_len integer DEFAULT 45, suffix text DEFAULT '...')
RETURNS text
AS $$
DECLARE
    suffix_len integer := length(suffix);
BEGIN
    RETURN CASE WHEN length(s) > max_len
        THEN left(s, max_len - suffix_len) || suffix
        ELSE s
    END;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION

Проверим:

=> SELECT shorten('Путешествия в некоторые удаленные страны мира в четырех частях: сочинение Лемюэля Гулливера, сначала хирурга, а затем капитана нескольких кораблей');
                    shorten                    
-----------------------------------------------
 Путешествия в некоторые удаленные страны м...
(1 row)

=> SELECT shorten('Путешествия в некоторые удаленные страны мира в четырех частях: сочинение Лемюэля Гулливера, сначала хирурга, а затем капитана нескольких кораблей', 30);
            shorten             
--------------------------------
 Путешествия в некоторые уда...
(1 row)

=> CREATE OR REPLACE FUNCTION book_name(book_id integer, title text)
RETURNS text
AS $$
SELECT shorten(title) || '. ' ||
       string_agg(author_name(a.last_name, a.first_name, a.middle_name), ', ' ORDER BY ash.seq_num)
FROM   authors a
       JOIN authorship ash ON a.author_id = ash.author_id
WHERE  ash.book_id = book_name.book_id;
$$ STABLE LANGUAGE sql;
CREATE FUNCTION

Функция shorten (перенос по словам)

=> CREATE OR REPLACE FUNCTION shorten(s text, max_len integer DEFAULT 45, suffix text DEFAULT '...')
RETURNS text
AS $$
DECLARE
    suffix_len integer := length(suffix);
    short text := suffix;
    pos integer;
BEGIN
    IF length(s) < max_len THEN
        RETURN s;
    END IF;
    FOR pos in 1 ..least(max_len-suffix_len+1, length(s)) LOOP
        IF substr(s,pos-1,1) != ' ' AND substr(s,pos,1) = ' ' THEN
            short := left(s, pos-1) || suffix;
        END IF;
    END LOOP;
    RETURN short;
END;
$$ IMMUTABLE LANGUAGE plpgsql;
CREATE FUNCTION

Проверим:

=> SELECT shorten('Путешествия в некоторые удаленные страны мира в четырех частях: сочинение Лемюэля Гулливера, сначала хирурга, а затем капитана нескольких кораблей');
                   shorten                   
---------------------------------------------
 Путешествия в некоторые удаленные страны...
(1 row)

=> SELECT shorten('Путешествия в некоторые удаленные страны мира в четырех частях: сочинение Лемюэля Гулливера, сначала хирурга, а затем капитана нескольких кораблей', 30);
          shorten           
----------------------------
 Путешествия в некоторые...
(1 row)