Как активировать PL/Python, примеры функции и процедуры
Чтобы использовать PL/Python, необходимо, чтобы модуль Python был установлен в вашей операционной системе для вашей версии PostgreSQL (например, пакет
postgresql-plpython3 в Linux), после чего его можно включить в нужной базе данных.1. Активация PL/Python
Активировать расширение нужно в целевой базе данных от имени суперпользователя (
postgres):SQL
CREATE EXTENSION IF NOT EXISTS plpython3u;
Важная деталь: Букваuна конце расширения означает untrusted (недоверенный). Это значит, что функции на PL/Python могут обращаться к файловой системе сервера, сети и операционной системе, поэтому создавать функции на PL/Python может только суперпользователь СУБД.
2. Пример функции (Function)
Функции в PostgreSQL возвращают значение. В PL/Python вы можете импортировать любые сторонние библиотеки Python (например,
json, math, requests, pandas и др.).Пример функции для парсинга и валидации JSON-строки с расчетом итоговой стоимости:
SQL
CREATE OR REPLACE FUNCTION calculate_cart_total(cart_json text)
RETURNS numeric AS $$
import json
try:
data = json.loads(cart_json)
items = data.get("items", [])
total = 0.0
for item in items:
price = item.get("price", 0)
quantity = item.get("quantity", 1)
total += price * quantity
return round(total, 2)
except Exception as e:
# raise_notice или log позволяют отправлять сообщения в клиент/лог базы
plpy.notice(f"Ошибка при обработке JSON: {e}")
return 0.0
$$ LANGUAGE plpython3u;
Вызов функции:
SQL
SELECT calculate_cart_total('{"items": [{"price": 100.5, "quantity": 2}, {"price": 50.0, "quantity": 1}]}');
-- Вернет: 251.00
3. Пример процедуры (Procedure)
Процедуры в PostgreSQL не возвращают результат и поддерживают управление транзакциями (
plpy.commit(), plpy.rollback()).Специальный модуль
plpy внутри PL/Python позволяет выполнять SQL-запросы внутри базы.Пример процедуры, которая находит устаревшие записи, отправляет их во внешнюю систему (имитация) и удаляет их:
SQL
CREATE OR REPLACE PROCEDURE cleanup_old_logs(days_old int)
AS $$
import time
# Выполняем SQL-запрос к БД с помощью plpy.execute
plan = plpy.prepare(
"SELECT id, message FROM system_logs WHERE created_at < NOW() - ($1 || ' days')::INTERVAL",
["int"]
)
result = plpy.execute(plan, [days_old])
plpy.info(f"Найдено записей для удаления: {len(result)}")
if len(result) > 0:
# Логика обработки записей на Python
for row in result:
log_id = row["id"]
# Здесь можно вызвать внешний API, сохранить резервную копию и т.д.
# Удаление записей
delete_plan = plpy.prepare(
"DELETE FROM system_logs WHERE created_at < NOW() - ($1 || ' days')::INTERVAL",
["int"]
)
plpy.execute(delete_plan, [days_old])
# Фиксация изменений
plpy.commit()
$$ LANGUAGE plpython3u;
Вызов процедуры:
SQL
CALL cleanup_old_logs(30);
Дополнительные возможности plpy
Внутри PL/Python вам автоматически доступен встроенный объект
plpy:-
plpy.execute("SELECT ...")— выполнение произвольного SQL-запроса. -
plpy.prepare(query, [types])— подготовка SQL-запроса для многократного выполнения. -
plpy.notice(msg),plpy.info(msg),plpy.warning(msg)— вывод сообщений пользователю. -
plpy.error(msg)— генерация исключения, отменяющего транзакцию.
Возвращают ли функции PL/Python наборы строк (recordsets) которые можно использовать в SQL-запросах?