Главная » Хабрахабр » Подсветка синтаксиса PostgreSQL

Подсветка синтаксиса PostgreSQL

Спешу поделиться хорошей новостью: жизнь авторов статей про PostgreSQL и их читателей стала немного лучше.

Не секрет также, что подсветка не всегда получается идеальной, и тогда авторы (которым не все равно, как выглядят их статьи) вынуждены заниматься самодеятельностью — расцвечивать свой код с помощью <font color=...>. Как знают все хаброписатели, для оформления исходного кода используется специальный тег <source>, который подсвечивает синтаксис.

Шло время, Алексей boomburum старательно исправлял мои font-ы на source (а я — обратно), пока не стало очевидно, что подсветку надо чинить. Особенно печально все было с PostgreSQL, поскольку подсветка охватывала более или менее стандартный SQL и категорически не понимала специфики нашей СУБД. И вот — готово, встречайте.
Наконец Далер daleraliyorov подсказал выход: добавить поддержку PostgreSQL в библиотеку highlightjs, которой пользуется Хабр.

pgsql: SQL, PL/pgSQL и все-все-все

Итак, секрет правильной подсветки — в новом языке pgsql. Его можно выбрать в меню (кнопка «исходный код») или указать вручную. В html для этого надо написать

<source lang="pgsql">
мой код
</source>

а в markdown — так:

Кроме того, автоопределение требует времени, так что если указать язык явно, код быстрее заиграет красками. ```pgsql
мой код
```

В принципе, highlightjs умеет определять язык сама, но нормально это работает только для больших фрагментов кода; на маленьких кусочках автоопределение часто промахивается.

Например, чтобы получить

CREATE TABLE aircrafts_data ( aircraft_code character(3) NOT NULL, model jsonb NOT NULL, range integer NOT NULL, CONSTRAINT aircrafts_range_check CHECK ((range > 0))
);

мы пишем

Например, чтобы получить <source lang="pgsql">
CREATE TABLE aircrafts_data (
    aircraft_code character(3) NOT NULL,
    model jsonb NOT NULL,
    range integer NOT NULL,
    CONSTRAINT aircrafts_range_check CHECK ((range > 0))
);
</source>

Тот же самый язык pgsql расцвечивает и код на PL/pgSQL.

CREATE FUNCTION get_available_flightid(date) RETURNS SETOF integer AS $$
BEGIN RETURN QUERY SELECT flightid FROM flight WHERE flightdate >= $1 AND flightdate < ($1 + 1); IF NOT FOUND THEN RAISE EXCEPTION 'Нет рейсов на дату: %.', $1; END IF; RETURN;
END
$$ LANGUAGE plpgsql;

пишем

Я рассматривал разные варианты, но именно этот показался наиболее адекватным. <source lang="pgsql">
CREATE FUNCTION get_available_flightid(date) RETURNS SETOF integer AS $$
...
$$ LANGUAGE plpgsql;
</source>

Небольшая тонкость состоит в том, что символьные строки, заключенные в доллары, всегда подсвечиваются как код, а строки в апострофах не подсвечиваются никогда.

Например, все будет работать и для PL/Perl: Способность highlightjs автоматически определять язык фрагмента позволяет подсвечивать функции и на других языках.

CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$ my ($x, $y) = @_; if (not defined $x) return $x if not defined $y; return $x if $x > $y; return $y;
$$ LANGUAGE plperl;

Для этого не нужно ничего специального, просто пишем

<source lang="pgsql">
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
...
$$ LANGUAGE plperl;
</source>

Конечно, выбранный язык зависит только от того, что написано внутри долларов, и никак не определяется тем, что написано после LANGUAGE.

В целом подсветка соответствует вышедшей недавно 11-й версии PostgreSQL.

К сожалению, чтобы отличить имя функции от, например, имени таблицы, нужен полноценный синтаксический разбор, а в рамках подсветки синтаксиса это не решается. Много сомнений было насчет подсветки функций. В итоге решил не расцвечивать вовсе — все равно все держится на ключевых словах, а пестроты поубавилось. Можно составить длинный список стандартных функций и расцвечивать их, но как быть с функциями из многочисленных расширений?

plaintext: текст, просто текст

Иногда в статье требуется оформить результаты запроса. Конечно, никаких ключевых слов там нет, подсвечивать ничего не нужно, но хочется, чтобы текст смотрелся «консольно», так же, как код. Для этого теперь можно использовать специальный язык plaintext. Например, чтобы получить

WITH xmldata(data) AS (VALUES ($$
<example xmlns="http://example.com/myns" xmlns:B="http://example.com/b"> <item foo="1" B:bar="2"/> <item foo="3" B:bar="4"/> <item foo="4" B:bar="5"/>
</example>$$::xml)
)
SELECT xmltable.* FROM XMLTABLE(XMLNAMESPACES('http://example.com/myns' AS x, 'http://example.com/b' AS "B"), '/x:example/x:item' PASSING (SELECT data FROM xmldata) COLUMNS foo int PATH '@foo', bar int PATH '@B:bar');

foo | bar
-----+----- 1 | 2 3 | 4 4 | 5
(3 rows)

пишем

<source lang="pgsql">
WITH xmldata(data) AS (VALUES ($$
...
</source>
<source lang="plaintext">
 foo | bar
-----+-----
   1 |   2
   3 |   4
   4 |   5
(3 rows)
</source>

Plaintext всегда надо указывать явно, автоматически он не определяется.

Если найдете ошибку в том, как подсвечивается код (а ошибки неизбежны, слишком уж контекстно-зависимый синтаксис у SQL), создавайте задачу на github проекта, а еще лучше — предлагайте решение. Надеюсь, что нововведение вам понравится и пригодится.

S. P. Заявки на доклады принимаются до 5 декабря! Не забывайте про конференцию PGConf, которая состоится 4–6 февраля в Москве.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Разработка buck-преобразователя на STM32F334: принцип работы, расчеты, макетирование

В двух своих последних статьях я рассказал о силовом модуле и плате управления на базе микроконтроллера STM32F334R8T6, которые созданы специально для реализации систем управления силовыми преобразователями и электроприводом. Так же был рассмотрен пример DC/AC преобразователя, который являлся демонстрацией, а не ...

Simulation theory: взаимосвязь квантово-химических расчётов и Реальности

Введение О чём этот текст Если человек услышит о «симуляции реальности», то в наиболее вероятно ему в голову придут или разные научно-фантастические произведения (типа Матрицы, Темного города, или Теоремы Зеро), или компьютерные игры. В случае людей, чьи головы засорены инженерным ...