Первое изменение исходного кода PostgreSQL

PostgreSQLДавно я думал об этом — и вот, сделал. Я хотел внести в исходный код PostgreSQL изменение, скомпилировать его и посмотреть на результат работы, чтобы мой измененный код заработал и я это увидел где-нибудь в интерфейсе.

Выбор мой упал на psql и его команды начинающиеся на бекслеш (типа \dt и подобные). Я решил добавить еще одну команду в этот список и запускать её когда нужно «погреть душу» и посмотреть на мои мега-изменения.

Понимаю что это всё для опытных людей (в данной сфере) всё это ясно, понятно и просто. Но я это делаю первый раз, много чего непонятно — и я рад, что всё задуманное у меня получилось.

Оглавление:

  1. Что будем менять — общая идея
  2. Что меняем в деталях
  3. Реализация
  4. Компиляция PostgreSQL
  5. Проверка \dh

1. Что будем менять — общая идея

Исходный код PostgreSQL можно взять в гитхабе проекта.

Итак, нужно сделать следующее — понять, как устроена «работа» команд, начинающихся на обратную косую черту. На самом деле я это сделал уже давно. Как можно догадаться, код, отвечающий за работу утилиты psql располагается в директории postgres/src/bin/psql.

Можно эту директорию открыть и онлайн — ссылка (я буду использовать 13ю версию сервера).

1. GitHub

Смотрим перечень файлов:

Обратите внимание на файл describe.c и его описание («psql \dP: reference regclass with «pg_catalog.» prefix»), начало команды «d» расшифровывается именно как describe. Есть еще один файл, ниже, describe.h, но он нам сейчас не нужен. Файлы с расширением .h в Си — это заголовочные файлы, содержимое которых добавляется в исходный код там, где мы укажем. Для интереса посмотрите его содержимое, но нам нужен именно describe.c.

В этом файле 6406 строк кода:

2. describe.c - кол-во строк

В самом начале файла располагаются полезные комментарии:

Support for the various \d («describe») commands. Note that the current expectation is that all functions in this file will succeed when working with servers of versions 7.4 and up. It’s okay to omit irrelevant information for an old server, but not to fail outright.

И:

Handlers for various slash commands displaying some sort of list of things in the database.

Листаем немного дальше — и как раз то, что нужно:

/*
 * \da
 * Takes an optional regexp to select particular aggregates
 */

И все остальные команды (\db, \dl и т.д.). Команд таких много, нужно найти такое сочетание букв, которых нет — чтобы это сочетание как раз использовать.

Путем нехитрого визуального просмотра начала файла можно заметить, что сочетание \dh не используется (хм, почему?). Вот его я и возьму.

На всякий случай — проверим, с помощью поиска по файлу:

3. dh не найдено

А еще можно в документации к psql посмотреть — там тоже такое сочетание не описано. Ну и можно выполнить эту команду в уже установленном psql’e:

4. dh не выполнилось

Команда не выполнилась. Убедились что она свободна и её можно использовать.

2. Что меняем в деталях

Теперь нужно понять из чего состоят команды \d[n] и как они вызываются. Работа команд оформлена в функции (например, describeFunctions). Но что-то мне подсказывает что их нужно откуда-то вызывать. Где-то должна быть явная проверка на ввода команды, т. к. в файле describe.c команды, начинающиеся на обратную косую черту в комментариях приведены, не в коде.

Для это я открыл postgres в редакторе Visual Studio Code (можно установить в Ubuntu). Нажал на любое название функции и выбрал пункт контекстного меню «Find All References» (найти все ссылки на эту функцию):

5. Find All References

В панели слева появится результат:

6. Результат в панели слева

Мне повезло, файлов совсем немного. Есть describe.h (я туда не полез, но, наверное, там тоже важно было бы добавить информацию о новой функции). И есть еще один файл, в той же директории — command.c. Переходим туда. Смотрим комментарии:

Handles all the different commands that start with ‘\’.

Как раз то, что нужно. А самое главное (и тут мне повезло), как раз тут и обрабатываются нужные команды. Поиском можно найти ту же функцию describeFunctions:

7. Список case

И как раз есть обработка букв в \d[N], через switch сделано. Круто, нашел!

Можно и в этом файле поискать что-нибудь про \dh. Я не нашел:

8. Case между G и L

Код оформлен очень красиво, структурировано. Можно просто его изучать — и уже какое-то понимание может появиться.

Итак, если я всё учёл — нужно добавить новую функцию в файл describe.c и обработчик этой функции в файл command.c — для сочетания \dh.

Попробуем.

3. Реализация

Тут у меня было несколько неудачных вариантов, я их в голове промотаю и описывать не буду. Зато опишу самый простой вариант — ведь у меня было желание изменить код и увидеть это изменение в работающем psql’e — это и сделаю.

Я полностью скопирую код существующей функции, только заменю её название и добавлю обработчик, который будет новую функцию вызывать для сочетания \dh. Пока задачи у меня нет разобраться как там всё функционирует, а для желания увидеть работу это идеально подходит.

По шагам:

1. Копирую и вставляю код функции describeAccessMethods (для сочетания \dA);

2. Задаю новое имя для скопированной функции: describeMyFunction;

3. Немного меню код новой функции. В самом конце (вроде бы) любой подобной функции есть вот такой код:

myopt.nullPrint = NULL;
myopt.title = _("List of access methods");
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
myopt.n_translate_columns = lengthof(translate_columns);

title можно заменить (много чего можно поменять, но я минимум изменений буду вносить). Сделаю так:

myopt.title = _("My Mega Function");

Всё просто 🙂

4. В файл command.c в соответствующее место (после case ‘g’:) добавлю обработчик для h:

case 'h':
    /* for my implementation \du */
	success = describeMyFunction(pattern, show_verbose, show_system);
    break;

(просто скопировал строки для ‘g’, заменил комментарий и название функции — на describeMyFunction).

Всё сохранил, файлы закрыл.

4. Компиляция PostgreSQL

Теперь нужно всё это скомпилировать — то есть установить PostgreSQL из исходных кодов.

Я пользовался этой инструкцией, что и вам рекомендую сделать.

Но кратко — команды для установки PostgreSQL:

./configure
make
make check
sudo make install

Если у вас ничего не настроено — тогда еще нужно создать пользователя и директорию для него:

sudo adduser postgres
sudo mkdir /usr/local/pgsql/data
sudo chown postgres /usr/local/pgsql/data/
sudo su - postgres

И далее добавляем пути в переменную $PATH (в статье по ссылке выше всё это подробно описано).

Запускаем сервер:

pg_ctl start

И запускаем psql:

psql

У меня всё заработало как нужно.

5. Проверка \dh

А теперь самое приятное — для чего все эти шаги выше были сделаны.

Запускаем команду \dh:

\dh

9. Результат работы dh

Помимо того что сочетание \dh отрабатывает, так еще и заголовок тот, который я задал в коде — My Mega Function.

Вот таким вот образом можно внести изменения в код PostgreSQL и увидеть, как он работает. А еще в коде можно увидеть больше информации, чем есть в документации — больше деталей.

Изменение очень небольшое, но ощущения приятные 🙂


Be the first to comment

Leave a Reply

Ваш Mail не будет опубликован.


*