無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

43.3. データ値

一般的にいって、PL/Pythonの目標はPostgreSQLとPythonの世界の間で "自然な" 対応付けを提供することです。 これは以下のようなデータの対応付けを形成します。

43.3.1. データ型の対応付け

関数引数は、以下のようにPostgreSQLの型から対応するPython型に変換されます。

  • PostgreSQLの boolean はPythonの bool に変換されます。

  • PostgreSQLの smallint および int はPythonの int に変換されます。 PostgreSQLの bigint および oid は、Python 2では long に、Python 3では int に変換されます。

  • PostgreSQLの real double および numeric はPythonの float に変換されます。 numeric では情報が失われ、間違った結果をもたらす可能性があることに注意してください。 将来のリリースでこれは修正されるかもしれません。

  • PostgreSQLの bytea は、Python 2では str に、Python 3では bytes に変換されます。 Python 2では文字列は文字符号化方式を持たないバイト列として扱われるはずです。

  • PostgreSQLの文字列型を含む、上記以外のデータ型はすべてPythonの str に変換されます。 Python 2ではこの文字列はPostgreSQLのサーバ符号化方式で表されます。 Python 3ではすべての文字列と同様にUnicode文字列となります。

  • スカラ型以外については後述します。

関数の戻り値は、以下のようにPostgreSQLの宣言された戻り値データ型に変換されます。

  • PostgreSQLの戻り値の型が boolean の場合、戻り値は Python の規約に従った真に対して評価されます。 つまり、0や空文字列は偽です。 'f' が真となることには注意してください。

  • PostgreSQLの戻り値の型が bytea の場合、戻り値は文字列(Python 2)またはbytes(Python 3)に、それぞれ対応するPythonのビルトインを使用して変換され、その結果が bytea に変換されます。

  • この他のPostgreSQLの戻り値型では、返されるPythonの値はPythonのビルトイン str を使用して文字列に変換され、その結果がPostgreSQLデータ型の入力関数に渡されます。

    Python 2における文字列はPostgreSQLに渡される時にPostgreSQLサーバの符号化方式でなければなりません。 現在のサーバ符号化方式で無効な文字列はエラーとなりますが、符号化方式の不一致がすべて検知されることはありません。 このため正確に行われなかった場合にはゴミデータという結果になります。 Unicode文字列は自動的に正しい符号化方式に変換されます。 このためこれを使用することがより安全でより便利です。 Python 3における文字列はすべてUnicode文字列です。

  • スカラデータ型以外については後述します。

宣言されたPostgreSQLの戻り値型と実際に返されるオブジェクトのPythonデータ型との間の論理的な不整合が伝わらないことに注意してください。 値はいかなる場合でも変換されます。

43.3.2. NullとNone

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 という値を返してください。 関数を厳密とした場合でも厳密としない場合でも、これを行うことができます。

43.3.3. 配列、リスト

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)

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
);

を前提とします。 複合型の結果は以下のように返されます。

シーケンス型(タプルまたはリスト。ただしインデック付けができないため set は不可)

返されるシーケンスオブジェクトは、結果の複合型が持つフィールドと同じ項目数をもたなければなりません。 0というインデックスの項目が複合型の最初のフィールド、1が次のフィールド、、、となります。 以下に例を示します。

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 を挿入してください。

オブジェクト( __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 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 tuple containing lists as composite types
  # all other combinations work also
  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;

警告

Pythonの bug #1483133 のため、一部のPython 2.4デバッグ版( --with-pydebug オプション付きで設定/コンパイルされたPython)が、集合結果を返すためにイテレータを使用する場合に PostgreSQL サーバをクラッシュさせることがわかっています。 未パッチのFedora 4にはこの不具合があります。 Python運用版やパッチ適用済みのFedora 4ではこの問題は起こりません。

RETURNS SETOF record を使用して) OUT パラメータを持つ集合を返す関数もサポートされます。 以下に例を示します。

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);


powered by SEO.CUG.NET