PostgreSQL の PL/Python を試してみる
PostgreSQL にはストアドプロシージャ(ファンクション)に Perl や Python といったスクリプト言語で記述できる。
これを使えば Perl/Python で外部のサーバにメッセージを飛ばせないかやってみた。
まずは MacPorts で PostgreSQL8.4 をインストール(9.x を使わなかったのには既存の環境が 8.x だったため)。
$ sudo port install postgresql84 +earthdistance +perl +python $ sudo port install posrgresql84-server $ sudo port load postgresql84-server $ sudo mkdir -p /opt/local/var/db/postgresql84/defaultdb $ sudo chown postgres:postgres /opt/local/var/db/postgresql84/defaultdb $ sudo su postgres -c '/opt/local/lib/postgresql84/bin/initdb -E UTF-8 --no-locale -D /opt/local/var/db/postgresql84/defaultdb' $ sudo ln -s /opt/local/lib/postgresql84/bin/pg_ctl /opt/local/bin $ sudo ln -s /opt/local/lib/postgresql84/bin/postgres /opt/local/bin $ sudo ln -s /opt/local/lib/postgresql84/bin/psql /opt/local/bin $ sudo su postgres -c 'pg_ctl -D /opt/local/var/db/postgresql84/defaultdb start'
sample というデータベースを作成し、psql でログインする。
$ psql --host 'localhost' --port 5432 --username 'postgres' 'sample' psql (8.4.9) Type "help" for help. sample=#
PL/Python を利用できるようにする。
sample=# CREATE PROCEDURAL LANGUAGE 'plpythonu' HANDLER plpython_call_handler; NOTICE: using pg_pltemplate information instead of CREATE LANGUAGE parameters CREATE LANGUAGE
次のような関数を定義する
CREATE OR REPLACE FUNCTION urlpost(IN arg text) RETURNS boolean AS $$ import urllib url = 'http://localhost:5000/sample/' params = urllib.urlencode({'post': arg}) f = urllib.urlopen(url, params) if f.read(): return True return False $$ LANGUAGE 'plpythonu' VOLATILE;
上記を psql にコピペで登録する。
sample=# CREATE OR REPLACE FUNCTION urlpost(IN arg text) RETURNS boolean AS sample-# $$ sample$# import urllib sample$# url = 'http://localhost:5000/sample/' sample$# params = urllib.urlencode({'post': arg}) sample$# f = urllib.urlopen(url, params) sample$# if f.read(): sample$# return True sample$# return False sample$# $$ sample-# LANGUAGE 'plpythonu' VOLATILE; CREATE FUNCTION
これで登録完了。
続いて Web アプリをつくる。
#!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Flask, render_template, request app = Flask(__name__) @app.route('/sample/', methods=['POST'], strict_slashes=False) def post(): data = request.form app.logger.info(data) return 'Success' if __name__ == '__main__': app.debug = True app.run(host='localhost', port=5000)
単純に http://localhost:5000/sample/ に POST があればログを吐いて Success を返すだけ。
psql で次のように呼び出す。
sample=# select urlpost('sample'); urlpost --------- t (1 row)
Python 側のログ
$ python app.py * Running on http://localhost:5000/ * Restarting with reloader -------------------------------------------------------------------------------- INFO in app [app.py:24]: ImmutableMultiDict([('post', u'sample')]) -------------------------------------------------------------------------------- 127.0.0.1 - - [06/Oct/2011 22:23:10] "POST /sample/ HTTP/1.0" 200 -
というわけで無事に外部にメッセージを送信する事が出来た。
PostgreSQL すげー。