43.3. ÐнаÑÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
ÐообÑе говоÑÑ, ÑÐµÐ»Ñ Ð¸ÑполниÑÐµÐ»Ñ PL/Python â обеÑпеÑиÑÑ Â«ÐµÑÑеÑÑвенное» ÑооÑвеÑÑÑвие Ð¼ÐµÐ¶Ð´Ñ Ð¼Ð¸Ñами PostgreSQL и Python. ÐÑим обÑÑÑнÑеÑÑÑ Ð²ÑÐ±Ð¾Ñ Ð¿Ñавил ÑопоÑÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ , опиÑаннÑÑ Ð½Ð¸Ð¶Ðµ.
43.3.1. СопоÑÑавление Ñипов даннÑÑ
Ðогда вÑзÑваеÑÑÑ ÑÑнкÑÐ¸Ñ PL/Python, ÐµÑ Ð°ÑгÑменÑÑ Ð¿ÑеобÑазÑÑÑÑÑ Ð¸Ð· Ñипа PostgreSQL в ÑооÑвеÑÑÑвÑÑÑий Ñип Python по Ñаким пÑавилам:
Тип PostgreSQL
booleanпÑеобÑазÑеÑÑÑ Ð²boolÑзÑка Python.Ð¢Ð¸Ð¿Ñ PostgreSQL
smallintиintпÑеобÑазÑÑÑÑÑ Ð² ÑипintÑзÑка Python. Ð¢Ð¸Ð¿Ñ PostgreSQLbigintиoidÑÑановÑÑÑÑ Ñипамиlongв Python 2 иintв Python 3.Ð¢Ð¸Ð¿Ñ PostgreSQL
realиdoubleпÑеобÑазÑÑÑÑÑ Ð² ÑипfloatÑзÑка Python.Тип PostgreSQL
numericпÑеобÑазÑеÑÑÑ Ð²DecimalÑÑÐµÐ´Ñ Python. ÐÑÐ¾Ñ Ñип импоÑÑиÑÑеÑÑÑ Ð¸Ð· пакеÑаcdecimal, пÑи его налиÑии. РпÑоÑивном ÑлÑÑае иÑполÑзÑеÑÑÑdecimal.Decimalиз ÑÑандаÑÑной библиоÑеки. ТипcdecimalÑабоÑÐ°ÐµÑ Ð·Ð½Ð°ÑиÑелÑно бÑÑÑÑее, Ñемdecimal. Ðднако в Python веÑÑии 3.3 и вÑÑе ÑипcdecimalвклÑÑаеÑÑÑ Ð² ÑÑандаÑÑнÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾ÑÐµÐºÑ Ð¿Ð¾Ð´ именемdecimal, Ñак ÑÑо ÑепеÑÑ ÑÑого ÑазлиÑÐ¸Ñ Ð½ÐµÑ.Тип PostgreSQL
byteaÑÑановиÑÑÑ Ñипомstrв Python 2 иbytesв Python 3. Ð Python 2 ÑакÑÑ ÑÑÑÐ¾ÐºÑ ÑледÑÐµÑ Ð²Ð¾ÑпÑинимаÑÑ ÐºÐ°Ðº поÑледоваÑелÑноÑÑÑ Ð±Ð°Ð¹Ñ Ð±ÐµÐ· какой-либо опÑеделÑнной кодиÑовки Ñимволов.ÐÑе дÑÑгие ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ , вклÑÑÐ°Ñ ÑÐ¸Ð¿Ñ ÑимволÑнÑÑ ÑÑÑок PostgreSQL, пÑеобÑазÑÑÑÑÑ Ð² Ñип
strÑзÑка Python. Ð Python 2 ÑÑа ÑÑÑока бÑÐ´ÐµÑ Ð¿ÐµÑедаваÑÑÑÑ Ð² кодиÑовке ÑеÑвеÑа Postgres Pro; в Python 3 ÑÑо бÑÐ´ÐµÑ ÑÑÑока в Unicode, как и вÑе ÑÑÑоки.ÐнÑоÑмаÑÐ¸Ñ Ð¾ неÑкалÑÑнÑÑ ÑÐ¸Ð¿Ð°Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¿Ñиведена ниже.
ÐÑи завеÑÑении ÑÑнкÑии PL/Python ÐµÑ Ð·Ð½Ð°Ñение ÑезÑлÑÑаÑа пÑеобÑазÑеÑÑÑ Ð² Ñип даннÑÑ , обÑÑвленнÑй как Ñип ÑезÑлÑÑаÑа в PostgreSQL, ÑледÑÑÑим обÑазом:
Ðогда Ñип ÑезÑлÑÑаÑа ÑÑнкÑии в PostgreSQL â
boolean, возвÑаÑаемое знаÑение пÑиводиÑÑÑ Ðº логиÑеÑÐºÐ¾Ð¼Ñ ÑÐ¸Ð¿Ñ Ð¿Ð¾ пÑавилам, пÑинÑÑÑм в Python. То еÑÑÑ false бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑено Ð´Ð»Ñ 0 и пÑÑÑой ÑÑÑоки, но, обÑаÑиÑе внимание, длÑ'f'бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑено true.Ðогда Ñип ÑезÑлÑÑаÑа ÑÑнкÑии PostgreSQL â
bytea, возвÑаÑаемое знаÑение бÑÐ´ÐµÑ Ð¿ÑеобÑазовано в ÑÑÑÐ¾ÐºÑ (Python 2) или Ð½Ð°Ð±Ð¾Ñ Ð±Ð°Ð¹Ñ (Python 3), иÑполÑзÑÑ Ð²ÑÑÑоеннÑе ÑÑедÑÑва Python, а заÑем бÑÐ´ÐµÑ Ð¿Ñиведено к ÑипÑbytea.ÐÐ»Ñ Ð²ÑÐµÑ Ð´ÑÑÐ³Ð¸Ñ Ñипов ÑезÑлÑÑаÑа PostgreSQL возвÑаÑаемое знаÑение пÑеобÑазÑеÑÑÑ Ð² ÑÑÑÐ¾ÐºÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð²ÑÑÑоенной в Python ÑÑнкÑии
str, и полÑÑÐµÐ½Ð½Ð°Ñ ÑÑÑока пеÑедаÑÑÑÑ ÑÑнкÑии ввода Ñипа даннÑÑ PostgreSQL. (ÐÑли знаÑение в Python Ð¸Ð¼ÐµÐµÑ Ñипfloat, оно пÑеобÑазÑеÑÑÑ Ð²ÑÑÑоенной ÑÑнкÑиейrepr, а неstr, Ð´Ð»Ñ Ð½ÐµÐ´Ð¾Ð¿ÑÑÐµÐ½Ð¸Ñ Ð¿Ð¾ÑеÑи ÑоÑноÑÑи.)Ðз кода Python 2 ÑÑÑоки Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÐµÑедаваÑÑÑÑ Ð² Postgres Pro в кодиÑовке ÑеÑвеÑа Postgres Pro. ÐÑи пеÑедаÑе ÑÑÑоки, непÑиемлемой Ð´Ð»Ñ ÑекÑÑей кодиÑовки ÑеÑвеÑа, Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ Ð¾Ñибка, но не вÑе неÑооÑвеÑÑÑÐ²Ð¸Ñ ÐºÐ¾Ð´Ð¸Ñовки могÑÑ Ð±ÑÑÑ Ð²ÑÑвленÑ, Ñак ÑÑо Ñ Ð½ÐµÐºÐ¾ÑÑекÑной кодиÑовкой вÑÑ Ð¶Ðµ могÑÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÑÑÐµÐ½Ñ Ð½ÐµÑиÑаемÑе ÑÑÑоки. СÑÑоки Unicode пеÑеводÑÑÑÑ Ð² нÑжнÑÑ ÐºÐ¾Ð´Ð¸ÑÐ¾Ð²ÐºÑ Ð°Ð²ÑомаÑиÑеÑки, Ñак ÑÑо иÑполÑзоваÑÑ Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñнее и Ñдобнее. Ð Python 3 вÑе ÑÑÑоки имеÑÑ ÐºÐ¾Ð´Ð¸ÑÐ¾Ð²ÐºÑ Unicode.
ÐнÑоÑмаÑÐ¸Ñ Ð¾ неÑкалÑÑнÑÑ ÑÐ¸Ð¿Ð°Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¿Ñиведена ниже.
ÐамеÑÑÑе, ÑÑо логиÑеÑкие неÑооÑвеÑÑÑÐ²Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñ Ð¾Ð±ÑÑвленнÑм в PostgreSQL Ñипом ÑезÑлÑÑаÑа и Ñипом ÑакÑиÑеÑки возвÑаÑаемого обÑекÑа Python игноÑиÑÑÑÑÑÑ â знаÑение пÑеобÑазÑеÑÑÑ Ð² лÑбом ÑлÑÑае.
43.3.2. Null, None
ÐÑли ÑÑнкÑии пеÑедаÑÑÑÑ Ð·Ð½Ð°Ñение SQL NULL, в Python знаÑением ÑÑого аÑгÑменÑа бÑÐ´ÐµÑ None. ÐапÑимеÑ, ÑÑнкÑÐ¸Ñ pymax, опÑеделÑÐ½Ð½Ð°Ñ ÐºÐ°Ðº показано в Раздел 43.2, возвÑаÑÐ¸Ñ Ð½ÐµÐ²ÐµÑнÑй оÑвеÑ, полÑÑив аÑгÑменÑÑ NULL. ÐÑ Ð¼Ð¾Ð³Ð»Ð¸ Ð±Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸ÑÑ Ñказание STRICT в опÑеделение ÑÑнкÑии, ÑÑÐ¾Ð±Ñ Postgres Pro поÑÑÑпал немного ÑазÑмнее: пÑи пеÑедаÑе знаÑÐµÐ½Ð¸Ñ 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. ÐÑо можно ÑделаÑÑ Ð¸ в ÑÑÑогой, и в неÑÑÑогой ÑÑнкÑии.
43.3.3. ÐаÑÑивÑ, ÑпиÑки
ÐнаÑÐµÐ½Ð¸Ñ Ð¼Ð°ÑÑивов SQL пеÑедаÑÑÑÑ Ð² PL/Python в виде ÑпиÑка Python. ЧÑÐ¾Ð±Ñ Ð²ÐµÑнÑÑÑ Ð¼Ð°ÑÑив SQL из ÑÑнкÑии PL/Python, возвÑаÑиÑе поÑледоваÑелÑноÑÑÑ 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)43.3.4. СоÑÑавнÑе ÑипÑ
ÐÑгÑменÑÑ ÑоÑÑавного Ñипа пеÑедаÑÑÑÑ ÑÑнкÑии в виде ÑопоÑÑавлений 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 â вÑоÑÐ¾Ð¼Ñ Ð¸ Ñ. д. ÐапÑимеÑ:
CREATE FUNCTION make_pair (name text, value integer) RETURNS named_value AS $$ return [ name, value ] # или в виде коÑÑежа: 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Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ ÑооÑвеÑÑÑвÑÑÑего ÑÑолбÑа в каÑеÑÑве клÑÑа.- ÐбÑÐµÐºÑ (лÑбой обÑÐµÐºÑ Ñ Ð¼ÐµÑодом
__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) # или пÑоÑÑо 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();
43.3.5. ФÑнкÑии, возвÑаÑаÑÑие множеÑÑва
ФÑнкÑÐ¸Ñ PL/Python Ñакже Ð¼Ð¾Ð¶ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑва, ÑодеÑжаÑие ÑкалÑÑнÑе и ÑоÑÑавнÑе ÑипÑ. ÐÑо можно оÑÑÑеÑÑвиÑÑ ÑазнÑми ÑпоÑобами, Ñак как возвÑаÑаемÑй обÑÐµÐºÑ Ð²Ð½ÑÑÑи пÑевÑаÑаеÑÑÑ Ð² иÑеÑаÑоÑ. Ð ÑледÑÑÑÐ¸Ñ Ð¿ÑимеÑÐ°Ñ Ð¿ÑедполагаеÑÑÑ, ÑÑо Ñ Ð½Ð°Ñ ÐµÑÑÑ ÑоÑÑавной Ñип:
CREATE TYPE greeting AS ( how text, who text );
ÐножеÑÑво в каÑеÑÑве ÑезÑлÑÑаÑа можно возвÑаÑиÑÑ, пÑименив:
- ÐоÑледоваÑелÑноÑÑÑ (коÑÑеж, ÑпиÑок, множеÑÑво)
CREATE FUNCTION greet (how text) RETURNS SETOF greeting AS $$ # возвÑаÑÐ°ÐµÑ ÐºÐ¾ÑÑеж, ÑодеÑжаÑий ÑпиÑки в каÑеÑÑве ÑоÑÑавнÑÑ Ñипов # Ñакже бÑдÑÑ ÑабоÑаÑÑ Ð¸ оÑÑалÑнÑе комбинаÑии return ( [ how, "World" ], [ how, "PostgreSQL" ], [ how, "PL/Python" ] ) $$ LANGUAGE plpythonu;
- ÐÑеÑаÑÐ¾Ñ (лÑбой обÑекÑ, ÑеализÑÑÑий меÑодÑ
__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 plpythonu;- ÐенеÑаÑÐ¾Ñ (
yield) CREATE FUNCTION greet (how text) RETURNS SETOF greeting AS $$ for who in [ "World", "PostgreSQL", "PL/Python" ]: yield ( how, who ) $$ LANGUAGE plpythonu;ÐÑедÑпÑеждение
Ðз-за оÑибки 1483133 в Python, некоÑоÑÑе оÑладоÑнÑе веÑÑии Python 2.4 (ÑконÑигÑÑиÑованнÑе и ÑкомпилиÑованнÑе Ñ ÐºÐ»ÑÑом
--with-pydebug) вÑводÑÑ Ð¸Ð· ÑÑÑÐ¾Ñ ÑеÑÐ²ÐµÑ Postgres Pro, когда иÑеÑаÑÐ¾Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ Ð½Ð°Ð±Ð¾Ñ ÑезÑлÑÑаÑов. ÐÑа оÑибка пÑоÑвлÑеÑÑÑ Ð² неиÑпÑавленнÑÑ Ð²ÐµÑÑиÑÑ Fedora 4, но не в вÑпÑÑкаемÑÑ Ð²ÐµÑÑиÑÑ Python и в иÑпÑавленной Fedora 4.
Также поддеÑживаÑÑÑÑ ÑÑнкÑии, возвÑаÑаÑÑие множеÑÑва, Ñ Ð¿Ð°ÑамеÑÑами OUT (обÑÑвленнÑе Ñ RETURNS SETOF record). ÐапÑимеÑ:
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);