一般而言,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
(在 Unicode 中,就像所有 Python 字串一樣)。
對於非純量資料類型,請參閱下文。
當 PL/Python 函數傳回時,其傳回值會轉換為函數宣告的 PostgreSQL 傳回資料類型,如下所示
當 PostgreSQL 傳回類型為 boolean
時,將根據Python規則評估傳回值的真偽。 也就是說,0 和空字串為 false,但值得注意的是 'f'
為 true。
當 PostgreSQL 傳回類型為 bytea
時,傳回值將使用各自的 Python 內建函數轉換為 Python bytes
,並且結果將轉換為 bytea
。
對於所有其他 PostgreSQL 傳回類型,傳回值會使用 Python 內建 str
轉換為字串,並且結果會傳遞到 PostgreSQL 資料類型的輸入函數。(如果 Python 值為 float
,則會使用 repr
內建函數而不是 str
進行轉換,以避免遺失精確度。)
當字串傳遞到 PostgreSQL 時,它們會自動轉換為 PostgreSQL 伺服器編碼。
對於非純量資料類型,請參閱下文。
請注意,宣告的 PostgreSQL 傳回類型和實際傳回物件的 Python 資料類型之間的邏輯不匹配不會被標記;無論如何都會轉換該值。
如果將 SQL null 值傳遞給函數,則引數值將在 Python 中顯示為 None
。例如,第 44.1 節中顯示的 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 plpython3u;
如上所示,要從 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 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)
其他 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);
如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的地方,請使用此表格來報告文件問題。