一般来说,PL/Python 的目标是在 PostgreSQL 和 Python 世界之间提供“自然”映射。这决定了下面描述的数据映射规则。
当调用 PL/Python 函数时,其参数将从其 PostgreSQL 数据类型转换为相应的 Python 类型。
PostgreSQL boolean
转换为 Python bool
。
PostgreSQL smallint
、int
、bigint
和 oid
转换为 Python int
。
PostgreSQL real
和 double
转换为 Python float
。
PostgreSQL numeric
转换为 Python Decimal
。如果可用,此类型将从 cdecimal
包导入。否则,将使用标准库中的 decimal.Decimal
。 cdecimal
明显快于 decimal
。但是,在 Python 3.3 及更高版本中,cdecimal
已集成到标准库中,名称为 decimal
,因此不再有任何区别。
PostgreSQL bytea
转换为 Python bytes
。
所有其他数据类型,包括 PostgreSQL 字符串类型,都转换为 Python str
(与所有 Python 字符串一样,使用 Unicode)。
对于非标量数据类型,请参见下文。
当 PL/Python 函数返回时,其返回值将转换为函数声明的 PostgreSQL 返回数据类型,如下所示:
当 PostgreSQL 返回类型为 boolean
时,返回值将根据Python规则评估真值。也就是说,0 和空字符串为假,但值得注意的是 'f'
为真。
当 PostgreSQL 返回类型为 bytea
时,返回值将使用相应的 Python 内置函数转换为 Python bytes
,结果将转换为 bytea
。
对于所有其他 PostgreSQL 返回类型,返回值将使用 Python 内置函数 str
转换为字符串,并将结果传递给 PostgreSQL 数据类型的输入函数。(如果 Python 值为 float
,则使用 repr
内置函数而不是 str
进行转换,以避免精度损失。)
字符串在传递给 PostgreSQL 时会自动转换为 PostgreSQL 服务器编码。
对于非标量数据类型,请参见下文。
请注意,声明的 PostgreSQL 返回类型与实际返回值对象的 Python 数据类型之间的逻辑不匹配不会被标记;无论如何,值都将被转换。
如果将 SQL 空值传递给函数,则参数值将在 Python 中显示为 None
。例如,第 44.1 节中显示的 pymax
函数定义将对空输入返回错误的答案。我们可以向函数定义中添加 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;
如上所示,要从 PL/Python 函数返回 SQL 空值,请返回 None
值。无论函数是否严格,都可以这样做。
SQL 数组值作为 Python 列表传递给 PL/Python。要从 PL/Python 函数返回 SQL 数组值,请返回 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)
多维数组作为嵌套的 Python 列表传递给 PL/Python。例如,二维数组是列表的列表。从 PL/Python 函数返回多维 SQL 数组时,每个级别的内部列表的大小必须相同。例如:
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)
为了向后兼容 PostgreSQL 9.6 及更低版本(当时不支持多维数组),其他 Python 序列(如元组)也被接受。但是,它们始终被视为一维数组,因为它们与复合类型存在歧义。出于同样的原因,当复合类型用于多维数组时,它必须由元组而不是列表表示。
请注意,在 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 映射传递给函数。映射的元素名称是复合类型的属性名称。如果传递的行中的属性具有空值,则它在映射中具有 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 空值,请在相应的位置插入 None
。
当返回复合类型的数组时,它不能作为列表返回,因为不清楚 Python 列表表示复合类型还是另一个数组维度。
每个结果类型列的值都从映射中检索,并使用列名称作为键。示例:
CREATE FUNCTION make_pair (name text, value integer) RETURNS named_value AS $$ return { "name": name, "value": value } $$ LANGUAGE plpython3u;
任何额外的字典键/值对都将被忽略。缺少的键将被视为错误。要返回任何列的 SQL 空值,请插入 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);
如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用此表单报告文档问题。