PostgreSQL 9.5.3 中文手册 | |||
---|---|---|---|
上一页 | 上一级 | 章 43. PL/Python - Python 过程语言 | 下一页 |
一般来说,PL/Python的目的是提供PostgreSQL和Python世界之间的"自然"映射。 如下面描述的数据映射规则。
当调用PL/Python函数时,它的参数从它们的PostgreSQL数据类型转换为相应的Python类型:
PostgreSQL boolean转换成Python bool。
PostgreSQL smallint和int转换成Python int。 PostgreSQL bigint和oid在Python 2中转换成long, 在Python 3中转换成int。
PostgreSQL real和double 转换成Python float。
PostgreSQL numeric转换成Python Decimal。 这个类型是从cdecimal包中引入的,如果该包可用的话。 否则将使用来自标准库的decimal.Decimal。 cdecimal比decimal明显快的多。 在Python 3.3及更高版本中,cdecimal已经以decimal 的名字合并到标准库中了,所以不再有任何不同了。
PostgreSQL bytea在Python 2中转换成Python str, 在Python 3中转换成bytes。在Python 2 中,字符串应被视为没有任何字符编码的字节序列。
所有其他数据类型,包括PostgreSQL字符串类型,转换为Python str。 在Python 2中,这个字符串将以PostgreSQL服务器编码;在Python 3中,它是一个Unicode字符串,和所有的字符串一样。
对于非标量数据类型,见下文。
当PL/Python函数返回时,其返回值将转换为函数声明的PostgreSQL返回数据类型,如下所示:
当PostgreSQL返回类型是boolean,按照Python 规则返回值估计为真。也就是说,0和空字符串是假,但值得注意的是'f'是真。
当postgreSQL返回类型是bytea时,返回值将使用各自的Python内建被转换成字符串 (Python 2)或者字节(Python 3),其结果被转换成bytea。
对于所有其他PostgreSQL返回类型,返回值使用Python内建str 转换成字符串,结果传递到PostgreSQL数据类型的输入函数。 (如果该Python值是float类型,它使用repr内置而不是str 进行转换,以避免损失精度。)
当在Python 2中的字符串要传递到PostgreSQL时,要求它们是以PostgreSQL服务器编码。 在当前服务器编码中无效的字符串将引发错误,但不是所有的编码不匹配都可以被检测到, 因此当做的不正确时,仍然会产生垃圾数据。Unicode字符串自动转换为正确的编码, 所以它可以更安全,更方便的使用。在Python 3中,所有的字符串都是Unicode字符串。
对于非标量数据类型,见下文。
请注意,PostgreSQL声明的返回类型和实际返回对象的Python数据类型之间的逻辑不匹配是不标记的; 该值将在任何情况下被转换。
如果向函数传递了一个SQL null值,参数值在Python中将会显示为
None。比如,在第 43.2 节中显示的
pymax
的函数定义对于null输入将返回错误结果。
我们可以添加STRICT到函数定义,使得PostgreSQL
进行更加合理的操作:如果传入null值,函数将根本不会被调用,而是立即自动返回null。或者,
也可以在函数体中检查输入参数是否为null:
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 plpythonu;
如上所示,要从PL/Python函数中返回一个SQL null 值,返回None即可。 无论函数是否严格,这样做都有效。
SQL数组值作为Python列表传递给PL/Python。要从PL/Python函数返回一个SQL数组值, 只需返回一个Python序列,例如一个列表或元组:
CREATE FUNCTION return_arr() RETURNS int[] AS $$ return (1, 2, 3, 4, 5) $$ LANGUAGE plpythonu; SELECT return_arr(); return_arr ------------- {1,2,3,4,5} (1 row)
注意:在Python中,字符串是序列,这可能有不良影响,这可能是Python程序员熟悉的:
CREATE FUNCTION return_str_arr() RETURNS varchar[] AS $$ return "hello" $$ LANGUAGE plpythonu; 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 plpythonu;
有多种从Python函数返回行或复合类型的方法。下面的例子假定我们有:
CREATE TYPE named_value AS ( name text, value integer );
一个复合类型结果可以作为下列之一返回:
返回的序列对象必须与复合结果类型字段数相同。索引为0的项将被分配给复合类型的第一个字段, 索引为1的项分配给第2个字段,以此类推。比如:
CREATE FUNCTION make_pair (name text, value integer) RETURNS named_value AS $$ return [ name, value ] # or alternatively, as tuple: return ( name, value ) $$ LANGUAGE plpythonu;
要为任何字段返回SQL null,就在相应的位置插入None。
每个结果类型字段的值从映射中使用字段名作为键检索,例如:
CREATE FUNCTION make_pair (name text, value integer) RETURNS named_value AS $$ return { "name": name, "value": value } $$ LANGUAGE plpythonu;
任何额外的字典键/值对被忽略。丢失的键将被当作错误。要为任何字段返回SQL null值, 就以相应的字段名作为键插入None。
它的工作方式和映射一样,例如:
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 plpythonu;
也支持带有OUT参数的函数。例如:
CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$ return (1, 2) $$ LANGUAGE plpythonu; SELECT * FROM multiout_simple();
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 plpythonu;
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 plpythonu;
CREATE FUNCTION greet (how text) RETURNS SETOF greeting AS $$ for who in [ "World", "PostgreSQL", "PL/Python" ]: yield ( how, who ) $$ LANGUAGE plpythonu;
警告 |
由于Python bug #1483133的原因, 一些Python 2.4的调试版本(使用--with-pydebug选项配置和编译) 已知会让PostgreSQL服务器在使用迭代器返回集合时崩溃。 Fedora 4的应用补丁版本包含这个臭虫。但是在生产版本的Python或已经修补的Fedora 4上没有这个问题。 |
也支持带有OUT参数的设置返回函数(使用RETURNS SETOF记录)。 例如:
CREATE FUNCTION multiout_simple_setof(n integer, OUT integer, OUT integer) RETURNS SETOF record AS $$ return [(1, 2)] * n $$ LANGUAGE plpythonu; SELECT * FROM multiout_simple_setof(3);