44.1. Функции на PL/Python #
Функции на PL/Python объявляются стандартным образом с помощью команды CREATE FUNCTION:
CREATE FUNCTIONимя_функции
(аргументы
) RETURNSвозвращаемый_тип
AS $$ # Тело функции на PL/Python $$ LANGUAGE plpython3u;
Тело функции содержит просто скрипт на языке Python. Когда вызывается функция, её аргументы передаются в виде элементов списка args
; именованные аргументы также передаются скрипту Python как обычные переменные. С именованными аргументами скрипт обычно лучше читается. Результат из кода Python возвращается обычным способом: командой return
или yield
(в случае функции, возвращающей множество). Если возвращаемое значение не определено, Python возвращает None
. Исполнитель PL/Python преобразует None
языка Python в значение NULL языка SQL. В процедуре код Python должен возвращать None
(обычно для этого процедура завершается без оператора return
или используется оператор return
без аргумента); в противном случае выдаётся ошибка.
Например, функцию, возвращающее большее из двух целых чисел, можно определить так:
CREATE FUNCTION pymax (a integer, b integer) RETURNS integer AS $$ if a > b: return a return b $$ LANGUAGE plpython3u;
Код на Python, заданный в качестве тела объявляемой функции, становится телом функции Python. Например, для показанного выше объявления получается функция:
def __plpython_procedure_pymax_23456(): if a > b: return a return b
Здесь 23456 — это OID, который PostgreSQL присвоил данной функции.
Значения аргументов задаются в глобальных переменных. Согласно правилам видимости в Python, тонким следствием этого является то, что переменной аргумента нельзя присвоить внутри функции выражение, включающее имя самой этой переменной, если только эта переменная не объявлена глобальной в текущем блоке. Например, следующий код не будет работать:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ x = x.strip() # ошибка return x $$ LANGUAGE plpython3u;
так как присваивание x
значения делает x
локальной переменной для всего блока, и при этом x
в правой части присваивания оказывается ещё не определённой локальной переменной x
, а не параметром функции PL/Python. Добавив оператор global
, это можно исправить:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ global x x = x.strip() # теперь всё в порядке return x $$ LANGUAGE plpython3u;
Однако рекомендуется не полагаться на такие особенности реализации PL/Python, а принять, что параметры функции предназначены только для чтения.