Перейти к основному содержимому

pldebugger. Средство отладки plpgsql

Версия: 1.1.

В исходном дистрибутиве установлено по умолчанию: нет.

Связанные компоненты: plpgsql.

Схема размещения: ext.

pldebugger предоставляет API для выполнения функций с возможностью остановки в заданной точке, пошаговым выполнением, просмотром значений переменных.

Расширение интегрировано с инструментами pg_admin и dbeaver, которые предлагают графический интерфейс для разработки и отладки с использованием возможностей расширения. Функции API доступны напрямую из psql, так как реализованы в виде стандартных SQL-функций.

Доработка

Не производилась.

Ограничения

Для корректной работы pldebugger необходимо наличие plpgsql - расширения по работе с plpgsql.

Внимание!

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

Установка

sudo dnf install pangolin-pldebugger-{version_component}-{OS}.x86_64.rpm
Подсказка

Пример заполненной команды:

cd distributive

sudo apt-get -y install pangolin-pldebugger-1.1-sberlinux8.x86_64.rpm

Расширение использует общую разделяемую память сервера, поэтому должно быть добавлено в shared_preload_libraries:

shared_preload_libraries = 'plugin_debugger'

Для использования расширения на развернутой СУБД необходимо установить его в целевую БД:

CREATE EXTENSION pldebugger SCHEMA ext;

С помощью ключевого слова SCHEMA можно задать целевую схему для расширения, если этого аргумента нет — расширение будет установлено в первую найденную схему из search_path.

Настройка

В случае, если расширение используется совместно с расширением plpgsql_check, библиотека расширения должна быть указана первой при перечислении в shared_preload_libraries:

shared_preload_libraries = 'plugin_debugger,plpgsql_check'

::: admonition Примечание :class: note

Поскольку расширение реализует API для отладки функций и процедур, для работы с ним нужно использовать внешние графические инструменты. В настоящее время работа с данным расширением реализована в pgAdmin4 и DBeaver (в редакции Enterprise). При необходимости возможно использование функций расширения непосредственно в сеансе psql. :::

Архитектура отладчика PL/pgSQL

Отладчик PL/pgSQL реализован в виде трех взаимодействующих компонентов:

  1. Клиент — среда, в которой вызываются функции API. Обычно представляет собой графический интерфейс пользователя, который отображает исходный код, текущий стек вызовов, переменные и другие элементы, а также позволяет устанавливать точки останова и выполнять код пошагово. Клиент может работать на удаленной машине, отличной от той, где размещен сервер базы данных, например PgAdmin.
  2. Целевой сервер — серверная часть, которая запускает отлаживаемый код. Для обеспечения возможности отладки в него должна быть загружена библиотека plugin_debugger.so.
  3. Отладочный прокси — дополнительный серверный процесс, к которому подключает клиент. На нем выполняются функции API, методы pl_dbg*, а также библиотеки pldbgapi.so.

Клиент устанавливает обычное соединение через драйвер (libpq или jdbc) с отладочным прокси, как если бы подключался к обычной базе данных. После установки соединения, прокси вызывает функции API библиотеки plugin_debugger.so, которая в свою очередь подключается к целевому серверу на уровне ядра, прозрачным для клиента образом. Протокол между прокси и целевым сервером не видим для других пользователей. Методы pldbg_* из библиотек API предоставляют доступный интерфейс к средствам отладки.

Доступ к данным методам осуществляется при помощи SQL-функций, предоставляемых расширением. Доступ к этим функциям не ограничивается какими-либо дополнительными механизмами контроля — любой пользователь, имеющий право аутентификации и вызова соответствующих SQL-функций, может перехватить выполнение функции в любом сеансе при наличии информации об ее OID.

Ниже представлена схема взаимодействия компонентов отладчика:


debugger client *------ libpq --------* Proxy backend
(pgAdmin) *
|
pldebugger socket connection
|
*
application client *----- libpq -------* Target backend

Функции расширения

Функции pldebugger

Имя функции
Аргументы
Тип возвращаемого значения
Описание
pldbg_abort_target
session integer
boolean
Останавливает выполнение/отладку кода в сессии с переданным в аргументе PID. Возвращает true или false в зависимости от успешности остановки
pldbg_attach_to_port
portnumber integer
integer
Функция подключается к целевому объекту отладки, прослушивающему заданный порт. Клиент отладчика вызывает эту функцию в ответ на уведомление PLDBGBREAK (уведомление содержит номер порта, к которому необходимо подключиться). Функция возвращает дескриптор сеанса, который идентифицирует конкретный сеанс отладки. При вызове любой из функций с префиксом pldbg_*, нужно указать дескриптор сеанса, возвращаемый функцией pldbg_attach_to_port(). Клиент отладчика может поддерживать несколько одновременных сеансов благодаря многократному вызову pldbg_attach_to_port() (с разными номерами портов) и отслеживанию возвращаемых дескрипторов сеанса
pldbg_continue
session integer
breakpoint
Функция отправляет команду continue целевому объекту отладчика, а затем ожидает, пока он достигнет следующего исполняемого оператора. На выходе возвращается запись типа breakpoint, характеризующая точку останова и содержащая идентификатор функции, а также номер строки, в которой целевой объект в данный момент остановлен
pldbg_create_listener
Отсутствуют
integer
Функция создает сеанс отладки. Возвращает id сессии сеанса отладки
pldbg_deposit_value
session integer

varname text

linenumber integer

value text
boolean
Функция перезаписывает значение заданной переменной (идентифицируемой по имени и номеру строки). Аргумент value определяется как выражение, результатом которого должно быть значение с типом, аналогичным типу заданной переменной (или приводимым к нему типом)
pldbg_drop_breakpoint
session integer

func oid

linenumber integer
boolean
Функция удаляет локальную точку останова в целевом процессе
pldbg_get_breakpoints
session integer
setof breakpoint
Функция возвращает набор точек останова. Каждая запись в результирующем наборе идентифицирует точку останова
pldbg_get_proxy_info
Отсутствуют
proxyinfo
Функция извлекает небольшую коллекцию параметров с сервера, которые связаны с версией сервера и версией протокола API, реализованного расширением для взаимодействия с ним внешних графических инструментов (например, pgAdmin). Функция может быть вызвана (из клиентского процесса отладчика), чтобы узнать, с какой версией прокси-API происходит взаимодействие — если этой функции не существует, можно предположить, что обмен данными осуществляется с прокси-API версии 1
pldbg_get_source
session integer

func oid
text
Функция возвращает исходный код для заданной функции. Клиент отладчика всегда должен извлекать исходный код, вызывая данную функцию, вместо чтения pg_proc. Если вместо этого производится чтение pg_proc, то считываемый исходный код может не совпадать с исходным кодом, фактически выполняемым целевым объектом (поскольку исходный код мог быть изменен в другой транзакции). pldbg_get_source() всегда извлекает исходный код из целевого объекта и гарантирует, что получаемый на выходе исходный код является исходным кодом, выполняемым целевым объектом
pldbg_get_stack
session integer
setof frame
Функция возвращает набор записей, каждая из которых описывает один фрейм в стеке вызовов. В каждой записи содержится информация о соответствующем фреймворке, включая строковое представление, пригодное для отображения имени и значения каждого аргумента конкретного вызова.
pldbg_get_target_info
signature text

targettype char
targetinfo
Устаревшая функция, которая возвращает информацию о целевой отлаживаемой функции. Используется для обратной совместимости со старыми версиями pgAdmin. Для новых приложений получение информации из каталога происходит напрямую
pldbg_get_variables
session integer
setof var
Функция возвращает набор записей var. Записи в результирующем наборе содержат информацию об одной рассматриваемой локальной переменной (или параметре) во фреймворке стека. Каждая запись содержит имя переменной, номер строки, в которой была объявлена переменная, а также флаг, сообщающий, является ли имя уникальным в пределах области действия функции. Если имя не является уникальным, клиент отладчика может использовать номер строки для различия переменных с одинаковыми именами. Также каждая запись содержит флаг, используемый для определения, является ли переменная константной; флаг, определяющий, является ли переменная нулевой, а также тип данных переменной (OID соответствующего pg_type) с ее значением. Чтобы просмотреть переменные, определенные в другом фреймворке стека, необходимо вызвать pldbg_select_frame() для переключения внимания отладчика на конкретный фреймворк
pldbg_oid_debug
functionoid oid
integer
Функция получает информацию о функции с переданным OID из pg_proc и в случае, если функция найдена, информация о ней получена, а пользователь, запустивший ее является суперпользователем, устанавливается локальная точка останова в начале данной функции. В случае успеха возвращается 0, в противном случае - код ошибки
pldbg_select_frame
session integer

frame integer
breakpoint
Функция изменяет цель отладчика на указанный кадр (в стеке вызовов). При остановке отладчик переключается на наиболее глубоко вложенную функцию в стеке вызовов (так как это функция, которая выполняется в данный момент времени). Цель отладчика можно изменить на другие фреймворки стека с целью получения исходного кода для этого фреймворка, значения переменных в этом фреймворке и точек останова в целевом объекте. Отладчик остается на выбранном кадре до тех пор, пока он не будет изменен пользователем или пока целевой объект не остановится на другой точке останова. Функция возвращает запись типа breakpoint, содержащую идентификатор функции и номер строки, на которой целевой объект в данный момент остановлен
pldbg_set_breakpoint
session integer

func oid

linenumber integer
boolean
Функция регистрирует локальную точку останова в целевом процессе
pldbg_set_global_breakpoint
session integer

func oid

linenumber integer

targetpid integer
boolean
Функция регистрирует точку останова в глобальной структуре с точками останова. На вход принимает id сессии, в которой запущен отладчик, OID функции, которую планируется отлаживать, номер строки функции, на которую устанавливается точка останова, а также PID целевого процесса, в котором будет выполняться отлаживаемая функция
pldbg_step_into
session integer
breakpoint
Функция отправляет команду step/into целевому объекту отладчика, а затем ожидает, пока целевой объект достигнет следующего исполняемого оператора, и возвращает запись типа breakpoint
pldbg_step_over
session integer
breakpoint
Функция отправляет команду step/over целевому объекту отладчика, а затем ожидает, пока целевой объект достигнет следующего исполняемого оператора в текущей функции. Если целевой объект столкнется с точкой останова (например, в дочернем вызове) до перехода к следующей исполняемой строке, он остановится на точке останова. Функция возвращает запись типа breakpoint
pldbg_wait_for_breakpoint
session integer
breakpoint
Функция ожидает, пока целевой объект отладки достигнет точки останова. Необходимо вызвать функцию сразу после того, как pldbg_attach_to_port() вернет идентификатор сеанса.

Функция pldbg_wait_for_breakpoint() почти идентична функциям pldbg_step_into(), pldbg_step_over() и pldbg_continue() (все они ожидают целевого объекта), но эта функция не отправляет команду целевому объекту первой.
pldbg_wait_for_target
session integer
integer
Функция объявляет прокси-процесс активным отладчиком, ожидающим глобальных точек останова и возвращает дескриптор сеанса, который идентифицирует конкретный сеанс отладки. Когда вызывается любая из других функций pldbg, необходимо указать соответствующий дескриптор сеанса. Данный клиент отладчика может поддерживать несколько одновременных сеансов, вызывая pldbg_attach_to_port() много раз (с разными номерами портов) и отслеживая возвращаемые дескрипторы сеанса
plpgsql_oid_debug
functionoid oid
integer
Оболочка функции pldbg_oid_debug (functionoid oid) создана для обратной совместимости со старыми версиями pgAdmin

Типы данных расширения

Типы, добавляемые расширением:

  • breakpoint
  • frame
  • proxyinfo
  • targetinfo
  • var

Управление

Решение не оказывает влияния на кластерную архитектуру СУБД Pangolin, включая потоковую и логическую репликацию, процессы резервного копирования, интеграцию с СРК, а также сохраняет полную обратную совместимость с текущей версией СУБД Pangolin.

Поскольку решение предоставляет возможность перехвата исполнения функций и доступа к полному стеку выполнения plpgsql кода, необходимо обеспечить аудит вызовов функций из задействованных расширений.

Использование модуля

Отладка кода с помощью pgAdmin

  1. Запустите pgAdmin, подключитесь к БД.

  2. В pgAdmin найдите в дереве объектов БД функцию get_count(text, int), в опциях, доступных через выпадающее меню Debugging, установите режим Set breakpoint.

    Результат — открылось окно отладчика, в другой сессии ожидается запуск целевой функции.

  3. Откройте новую сессию psql и подключитесь к демонстрационной БД.

  4. В psql вызовите функцию:

    select * from get_count('pg_class', 2);.

    Результат — сессия psql зависла на выполнении функции.

  5. Перейдите в окно отладки pgAdmin.

    Результат — в окне отладчика появился код функции, выделена строка, на которой в данный момент остановлено выполнение функции.

  6. В отладчике осуществите step into.

    Результат — в окне отладчика выделена следующая строка, на которой остановилось выполнение функции.

  7. Проверьте вкладки с отладочной информацией.

    Результат — во вкладках с отладочной информацией отображается актуальная информация, включающая номер текущей строки, значения аргументов функции, значения локальных переменных функции и др.

  8. В отладчике выберите строку с номером 10 и установите точку останова, нажав на область рядом с номером строки левой кнопкой мыши.

    Результат — на выбранной строке появился символ точки останова рядом с номером строки.

  9. В отладчике нажмите кнопку continue.

    Результат — выполнение функции продолжилось до точки останова.

  10. В отладчике осуществите step into.

    Результат — в отладчике появился код вложенной функции и ее стек, курсор установлен на первой строке функции.

  11. В отладчике нажмите кнопку continue.

    Результат — выполнился код вложенной функции, в отладчике появился код родительской функции, выполнение остановилось на следующей после вызова вложенной функции строке.

  12. В отладчике осуществите step over.

    Результат — выполнился код вложенной функции без перехода в нее, выполнение остановилось на следующей строке.

  13. В отладчике нажмите кнопку stop.

    Результат — выполнение функции прервалось, в консоли psql появилось сообщение о том, что выполнение функции остановлено администратором.

  14. Закройте вкладку отладчика, закройте pgAdmin, закройте psql.

Отключение функциональности

Для отключения данной функциональности необходимо:

  1. Удалить расширение командой:
DROP EXTENSION pldebugger;
  1. Убрать библиотеку расширения plugin_debugger из shared_preload_libraries.
  2. Перезагрузить сервер СУБД:
pg_ctl restart

Ссылки на документацию разработчика

pldebugger: https://github.com/EnterpriseDB/pldebugger.