PostgreSQLのPL/Pythonを使ってみる

postgresql
PostgreSQL では手続き型言語(PL=Procedural Language)を使って定義する際に、PL/pgSQL 以外にも Pl/Tcl, PL/Perl, PL/Python などさまざまな言語を使えると知ったので、PL/Python を触ってみた。

最終目標

関数の引数に文字列を渡すと twitter の検索結果を返す関数を作成

環境

以下の環境を前提

  • OS : Ubuntu 12.04, 64-bit
  • PostgreSQL : 9.1
  • Python : 2.7
  • requests : 0.8.2(apt-get では←のバージョンだったので)$ apt-get install python-requests する

インストール

まずは PL/Python を使えるようにする。

インストール済み PL 言語は createlang コマンドで確認する

$ createlang --list test
Procedural Languages
  Name   | Trusted?
---------+----------
 plpgsql | yes

デフォルトでは PL 系の中では plpgsql だけが有効になっている。
apt-get でインストール可能な PL/Python をチェック

$ apt-cache search plpython
postgresql-plpython-9.1 - PL/Python procedural language for PostgreSQL 9.1
postgresql-plpython3-9.1 - PL/Python 3 procedural language for PostgreSQL 9.1
postgresql-plpython-8.4 - PL/Python procedural language for PostgreSQL 8.4

PostgreSQL 9.1 に 2.*系 Python をインストールしたいので postgresql-plpython-9.1 をインストール。

$ sudo apt-get install postgresql-plpython-9.1

次に利用したいデータベースに PL/Python をインストール。createlang でインストール先データベース名とともに指定。

$ createlang plpythonu test
$ createlang --list test
 Procedural Languages
   Name    | Trusted?
-----------+----------
 plpgsql   | yes
 plpythonu | no
$ psql test
...
test=# SELECT * FROM pg_available_extensions;
    name    | default_version | installed_version |                  comment
------------+-----------------+-------------------+-------------------------------------------
 plpythonu  | 1.0             | 1.0               | PL/PythonU untrusted procedural language
 plpgsql    | 1.0             | 1.0               | PL/pgSQL procedural language
(2 rows)

plpythonu が trusted=no で追加された。

Python2 と Python3 を明示的に区別したい場合は $ createlang plpython2u ...$ createlang plpython3u ... のようにする。$ createlang plpythonu ... とすると、先に見つかった Python が採用される。

Chapter 42.1. PL/Python – Python Procedural Language – Python 2 vs. Python 3
http://www.postgresql.org/docs/9.2/static/plpython-python23.html

関数の登録

関数は CREATE FUNCTION のシンタックスの $$ ブロック内に Python のコードをベチャッと書けばOK。
http://www.postgresql.org/docs/9.2/static/plpython-funcs.html

CREATE FUNCTION funcname (argument-list)
  RETURNS return-type
AS $$
  # PL/Python function body
$$ LANGUAGE plpythonu;

Python の requests(0.8.4) モジュールを使って twitter に検索を投げて本文を返す関数は以下。(PL/Python はplpython2u を利用)

CREATE OR REPLACE FUNCTION twitter(query text)
RETURNS SETOF text
AS $$
import json
import urllib
import requests
url = 'http://search.twitter.com/search.json?q=%s&rpp=5&include_entities=true&result_type=recent'
response = requests.get(url%urllib.quote(query))
response = json.loads(response.content)
plpy.warning(response['completed_in']) # logging
for tweet in response['results']:
    yield tweet['text']
$$ LANGUAGE plpython2u;

PL/Python には plpy という名前の ユーティリティーモジュールも用意されている。上の例では検索時間をログ出力(plpy.warning)している。

関数の確認

作成した関数を psql から確認するには \df コマンドを利用する。

test=# \df
                         List of functions
 Schema |  Name   | Result data type | Argument data types |  Type
--------+---------+------------------+---------------------+--------
 public | twitter | SETOF text       | query text          | normal
(1 row)

関数の実行

作成した関数を利用して Twitter に問い合わせる

#postgresql のハッシュタグで検索

test=# select twitter('#postgresql');
WARNING:  0.017
CONTEXT:  PL/Python function "twitter"
                                                            twitter
--------------------------------------------------------------------------------------------------------------------------------
 年末年始休暇の宿題だった、PostgreSQL用の日本語正規化テキスト型 ntext のプロトタイプができた。 http://t.co/iXuEddqy #postgresql
 RT @al3xandru: ♻ PostgreSQL GiST and GIN Index Types http://t.co/gGgEi6dh #PostgreSQL
 ♻ PostgreSQL GiST and GIN Index Types http://t.co/gGgEi6dh #PostgreSQL
 rsync-ing 40Gb of #postgresql databases takes longer than expected...
 pldebugger / pdbgapi en #PostgreSQL 9.2.2 - Fedora 17 #spanish #español http://t.co/daLOziR8
(5 rows)

「鷹狩」で検索

test=# select twitter('鷹狩');
WARNING:  0.016
CONTEXT:  PL/Python function "twitter"
                                                                                          twitter
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 @26ap6 お!イイネ!\(^o^)/小鷹狩さんで始まろう!
 チキパの衣装が薄手すぎると関西弁でやかり始める小鷹狩
 チキパは売れてないから布が買えないから袖がなくて寒いって小鷹狩さんがお怒りです
 小鷹狩頑張ってるわ!ほんま。
 朝の散歩終了をー 今日は僕の散歩エリアに鷹狩の方々が来ていたよ 鳥さんみんな逃げておー 写真は今日のではありませんが 白菜畑の白菜の上のカラスくん(さんかも?)です http://t.co/wuTdeij4
(5 rows)

関数の削除

PL 系関数はオーバーロードできるので、関数名だけでなく引数も含めてどの関数を削除するのか指定する

test=# drop function twitter(query text);
DROP FUNCTION

trusted/untrusted PL

PL系言語は大きく分けて trusted(pgSQL, Tcl, Perl)untrusted(TclU, PythonU) の2種類がある。(最後の ‘u’ は ‘untrusted’ を指している。)
trusted 系は安全に PL を実行するように、ファイル・システムの操作など、セキュリティ上問題のありそうな操作は行えないようになっている。
一方で untrusted 系にはそのような制約はない。

Chapter 38.1. Procedural Languages – Installing Procedural Languages
http://www.postgresql.org/docs/9.2/static/xplang-install.html

The optional key word TRUSTED specifies that the language does not grant access to data that the user would not otherwise have. Trusted languages are designed for ordinary database users (those without superuser privilege) and allows them to safely create functions and trigger procedures. Since PL functions are executed inside the database server, the TRUSTED flag should only be given for languages that do not allow access to database server internals or the file system. The languages PL/pgSQL, PL/Tcl, and PL/Perl are considered trusted; the languages PL/TclU, PL/PerlU, and PL/PythonU are designed to provide unlimited functionality and should not be marked trusted.

Chapter 42. PL/Python – Python Procedural Language
http://www.postgresql.org/docs/9.2/static/plpython.html

As of PostgreSQL 7.4, PL/Python is only available as an “untrusted” language, meaning it does not offer any way of restricting what users can do in it. It has therefore been renamed to plpythonu. The trusted variant plpython might become available again in future, if a new secure execution mechanism is developed in Python. The writer of a function in untrusted PL/Python must take care that the function cannot be used to do anything unwanted, since it will be able to do anything that could be done by a user logged in as the database administrator. Only superusers can create functions in untrusted languages such as plpythonu.

例えば trusted な PL/Perl でファイル操作を行う関数を定義しようとすると、エラーが発生する。
例は→のURLから http://www.postgresql.org/docs/9.2/static/plperl-trusted.html

CREATE FUNCTION badfunc() RETURNS integer AS $$
    my $tmpfile = "/tmp/badfile";
    open my $fh, '>', $tmpfile
        or elog(ERROR, qq{could not open the file "$tmpfile": $!});
    print $fh "Testing writing to a file\n";
    close $fh or elog(ERROR, qq{could not close the file "$tmpfile": $!});
    return 1;
$$ LANGUAGE plperl;

ERROR:  'open' trapped by operation mask at line 4.
CONTEXT:  compilation of PL/Perl function "badfunc"

関数の名前空間
PL/Python で定義した関数は PostgreSQL のサーバサイドの名前空間で定義される。
例えば、再帰呼び出しをするような場合は、関数を PostgreSQL サーバに問い合わせる必要がある。
再帰をつかって階乗を求める関数を定義すると、以下のようになる。

CREATE OR REPLACE FUNCTION fact(n integer)
RETURNS integer
AS $$
if n <= 1:
    return n
else:
    return n * plpy.execute("select fact(%d) as n" % (n-1))[0]["n"]
$$ LANGUAGE plpython2u;

test=# select fact(5);
 fact
------
  120
(1 row)

References

Advertisements
Tagged with: , ,
Posted in database

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
  • RT @__apf__: How to write a research paper: a guide for software engineers & practitioners. docs.google.com/presentation/d… /cc @inwyrd 4 months ago
  • RT @HayatoChiba: 昔、自然と対話しながら数学に打ち込んだら何かを悟れるのではと思いたち、専門書1つだけ持ってパワースポットで名高い奈良の山奥に1週間籠ったことがある。しかし泊まった民宿にドカベンが全巻揃っていたため、水島新司と対話しただけで1週間過ぎた。 それ… 5 months ago
  • RT @googlecloud: Ever wonder what underwater fiber optic internet cables look like? Look no further than this deep dive w/ @NatAndLo: https… 5 months ago
  • @ijin UTC+01:00 な時間帯で生活しています、、、 10 months ago
  • RT @mattcutts: Google's world-class Site Reliability Engineering team wrote a new book: amazon.com/Site-Reliabili… It's about managing produc… 1 year ago
%d bloggers like this: