Значения данных
Эта страница переведена при помощи нейросети GigaChat.
В общем и целом, цель PL/Python – предоставить «естественное» соответствие между мирами PostgreSQL и Python. Этим определяется выбор правил сопоставления данных, описанных ниже.
Сопоставление типов данных
Когда вызывается функция PL/Python, ее аргументы преобразуются из типа данных PostgreSQL в соответствующий тип Python:
- PostgreSQL
boolean
преобразуется в Pythonbool
. - PostgreSQL
smallint
,int
,bigint
иoid
преобразуются в Pythonint
. - PostgreSQL
real
иdouble
преобразуются в Pythonfloat
. - PostgreSQL
numeric
преобразуется в PythonDecimal
. Этот тип импортируется из пакетаcdecimal
, если он доступен. В противном случае будет использоватьсяdecimal.Decimal
из стандартной библиотеки.cdecimal
значительно быстрее, чемdecimal
. Однако в Python 3.3 и вышеcdecimal
был интегрирован в стандартную библиотеку под именемdecimal
, поэтому больше нет никакой разницы. - PostgreSQL
bytea
преобразуется в Pythonbytes
. - Все остальные типы данных, включая типы строк символов PostgreSQL, преобразуются в строку Python
str
(в Unicode, как и все строки Python). - Для нескалярных типов данных см. ниже.
Когда функция PL/Python возвращает значение, ее возвращаемое значение преобразуется в объявленный тип данных возврата PostgreSQL следующим образом:
-
Когда тип возврата PostgreSQL равен
boolean
, возвращаемое значение будет оценено на истинность в соответствии с правилами Python. То есть 0 и пустая строка ложны, а'f'
истинно. -
Когда тип возврата PostgreSQL равен
bytea
, возвращаемое значение будет преобразовано в Pythonbytes
с использованием соответствующих встроенных функций Python, причем результатом будет преобразование вbytea
. -
Для всех остальных типов возвращаемых значений PostgreSQL возвращаемое значение преобразуется в строку с использованием встроенной функции Python
str
, и результат передается входной функции типа данных PostgreSQL. Если значение Python являетсяfloat
, оно преобразуется с помощью встроенного методаrepr
вместоstr
, чтобы избежать потери точности.Строки автоматически преобразуются в кодировку сервера PostgreSQL при передаче в PostgreSQL.
-
Для нескалярных типов данных см. ниже.
Обратите внимание, что логические несоответствия между объявленным типом возвращаемого значения PostgreSQL и фактическим типом возвращаемого объекта Python не отмечаются, значение будет преобразовано в любом случае.
NULL, None
Если значение SQL NULL
передается функции, значение аргумента будет отображаться как None
в Python. Например, определение функции pymax
, показанное в разделе «Функции PL/Python», вернет неправильный ответ для пустых входных значений. Можно было бы добавить STRICT
к определению функции, чтобы заставить PostgreSQL делать что-то более разумное: если передается нулевое значение, функция вообще не вызывается, а просто автоматически возвращается нулевой результат. В качестве альтернативы можно проверить наличие нулевых входных данных в теле функции:
CREATE FUNCTION pymax (a integer, b integer)
RETURNS integer
AS $$
if (a is None) or (b is None):
return None
if a > b:
return a
return b
$$ LANGUAGE plpython3u;
Как показано выше, чтобы вернуть значение SQL NULL
из функции PL/Python, верните значение None
. Это можно сделать независимо от того, является ли функция строгой или нет.
Массивы, Списки
Значения массивов SQL передаются в PL/Python как список Python. Чтобы вернуть значение массива SQL из функции PL/Python, верните список Python:
CREATE FUNCTION return_arr()
RETURNS int[]
AS $$
return [1, 2, 3, 4, 5]
$$ LANGUAGE plpython3u;
SELECT return_arr();
return_arr
-------------
{1,2,3,4,5}
(1 row)
Многомерные массивы передаются в PL/Python как вложенные списки Python. Например, двумерный массив является списком списков. Когда многомерный массив SQL возвращается из функции PL/Python, внутренние списки на каждом уровне должны быть одинакового размера. Например:
CREATE FUNCTION test_type_conversion_array_int4(x int4[]) RETURNS int4[] AS $$
plpy.info(x, type(x))
return x
$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_int4(ARRAY[[1,2,3],[4,5,6]]);
INFO: ([[1, 2, 3], [4, 5, 6]], <type 'list'>)
test_type_conversion_array_int4
---------------------------------
{{1,2,3},{4,5,6}}
(1 row)
Другие последовательности Python, такие как кортежи, также принимаются для обратной совместимости с версиями PostgreSQL 9.6 и ниже, когда не поддерживались многомерные массивы. Однако они всегда рассматриваются как одномерные массивы, потому что они неоднозначны с составными типами. По той же причине, когда используется составной тип в многомерном массиве, он должен быть представлен кортежем, а не списком.
Обратите внимание, что в Python строки являются последовательностями, которые могут иметь нежелательные эффекты, которые могут быть знакомы программистам на Python:
CREATE FUNCTION return_str_arr()
RETURNS varchar[]
AS $$
return "hello"
$$ LANGUAGE plpython3u;
SELECT return_str_arr();
return_str_arr
----------------
{h,e,l,l,o}
(1 row)
Составные типы
Аргументы составного типа передаются функции как отображения Python. Имена элементов отображения – это имена атрибутов составного типа. Если атрибут в переданном ряду имеет значение NULL
, он имеет значение None
в отображении. Пример:
CREATE TABLE employee (
name text,
salary integer,
age integer
);
CREATE FUNCTION overpaid (e employee)
RETURNS boolean
AS $$
if e["salary"] > 200000:
return True
if (e["age"] < 30) and (e["salary"] > 100000):
return True
return False
$$ LANGUAGE plpython3u;
Существует несколько способов возврата строки или составных типов из функции Python. В следующих примерах предполагается, что есть:
CREATE TYPE named_value AS (
name text,
value integer
);
Составной результат может быть возвращен как:
-
Последовательность (кортеж или список, но не множество, потому что оно не индексируемо) – возвращаемые объекты последовательностей должны содержать столько же элементов, сколько полей имеет составной тип результата. Элемент с индексом 0 присваивается первому полю составного типа, 1 - второму и так далее. Например:
CREATE FUNCTION make_pair (name text, value integer)
RETURNS named_value
AS $$
return ( name, value )
# or alternatively, as list: return [ name, value ]
$$ LANGUAGE plpython3u;Чтобы вернуть SQL
NULL
для любого столбца, вставьтеNone
в соответствующее положение.Когда массив составных типов возвращается, он не может быть возвращен как список, потому что неясно, представляет ли список Python составной тип или другое измерение массива.
-
Сопоставление (словарь) – значение для каждого столбца типа результата извлекается из сопоставления с именем столбца в качестве ключа. Пример:
CREATE FUNCTION make_pair (name text, value integer)
RETURNS named_value
AS $$
return { "name": name, "value": value }
$$ LANGUAGE plpython3u;Любые дополнительные пары ключ/значение словаря игнорируются. Отсутствующие ключи обрабатываются как ошибки. Чтобы вернуть значение SQL
NULL
для любого столбца, вставьтеNone
с соответствующим именем столбца в качестве ключа. -
Объект (любой объект, предоставляющий метод
__getattr__
) – работает аналогично сопоставлению. Пример:CREATE FUNCTION make_pair (name text, value integer)
RETURNS named_value
AS $$
class named_value:
def __init__ (self, n, v):
self.name = n
self.value = v
return named_value(name, value)
# or simply
class nv: pass
nv.name = name
nv.value = value
return nv
$$ LANGUAGE plpython3u;
Функции с параметрами OUT
также поддерживаются. Например:
CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$
return (1, 2)
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_simple();
Выходные параметры процедур передаются обратно таким же образом. Например:
CREATE PROCEDURE python_triple(INOUT a integer, INOUT b integer) AS $$
return (a * 3, b * 3)
$$ LANGUAGE plpython3u;
CALL python_triple(5, 10);
Функции, возвращающие набор значений
Функция PL/Python также может возвращать наборы скалярных или составных типов. Есть несколько способов добиться этого, потому что возвращаемый объект внутренне преобразуется в итератор. В следующих примерах предполагается, что есть составной тип:
CREATE TYPE greeting AS (
how text,
who text
);
Множество в качестве результата можно возвратить, применив:
-
Последовательность (кортеж, список, набор):
CREATE FUNCTION greet (how text)
RETURNS SETOF greeting
AS $$
# return tuple containing lists as composite types
# all other combinations work also
return ( [ how, "World" ], [ how, "PostgreSQL" ], [ how, "PL/Python" ] )
$$ LANGUAGE plpython3u; -
Итератор (любой объект, реализующий методы
__iter__
иnext
):CREATE FUNCTION greet (how text)
RETURNS SETOF greeting
AS $$
class producer:
def __init__ (self, how, who):
self.how = how
self.who = who
self.ndx = -1
def __iter__ (self):
return self
def next (self):
self.ndx += 1
if self.ndx == len(self.who):
raise StopIteration
return ( self.how, self.who[self.ndx] )
return producer(how, [ "World", "PostgreSQL", "PL/Python" ])
$$ LANGUAGE plpython3u; -
Генератор (
yield
)CREATE FUNCTION greet (how text)
RETURNS SETOF greeting
AS $$
for who in [ "World", "PostgreSQL", "PL/Python" ]:
yield ( how, who )
$$ LANGUAGE plpython3u;
Функции, возвращающие множество с параметрами OUT
(используя RETURNS SETOF record
) также поддерживаются. Например:
CREATE FUNCTION multiout_simple_setof(n integer, OUT integer, OUT integer) RETURNS SETOF record AS $$
return [(1, 2)] * n
$$ LANGUAGE plpython3u;
SELECT * FROM multiout_simple_setof(3);