際際滷

際際滷Share a Scribd company logo
PL/Pythonで2咼▲廛蠅鰈ってみた
PostgreSQLカンファレンス2015/05
アシストセミナ`ル`ム
who am i
兆念:表弥 
氏芙:アシスト
碧並:ポスグレとオラクルのサポ`トしてます
定h:芙氏繁5定朕(ポスグレ4定伏)
廣吭
兜伉宀がやってみた狼です
飛孤ギャグなので伏哲かい朕でてください
9.5 について岑りたい圭は
書岷ぐ
○
Long Time Ago..
クラサバ
クライアントとデ`タベ`スが岷
ビジネスロジックはクライアント番佩
graph LR id1(クライアント
ロジック)-->id2(デ`タベ`ス) style id1 fill:#955,stroke:#111,stroke-
width:4px; style id2 fill:#559,stroke:#f66,stroke-width:2px;
3咼▲廛螢羽`ション
gにWEB/APサ`バえた
クライアント箸魯屮薀Ε
ビジネスロジックはWEB/APサ`バ
graph LR id1(クライアント:
ブラウザ)-->id2(WEBサ`バ:
ロジック) id2-->id3(DB) style id1 fill:#955,stroke:#111,stroke-
width:4px; style id2 fill:#555,stroke:#111,stroke-width:4px; style id3
fill:#559,stroke:#f66,stroke-width:2px;
でも...
砿尖とか
塞とか
堀業とか
そうだ2蚊にろう
できあがったもの
PG2LAYER
201505 PostgreSQLアンカンファレンス(PL/Pythonで恬るWEBアプリ)
PG2LAYER
PostgreSQL Two Layer Management System
砿尖喘のダッシュボ`ド
クエリY惚をJSONですAPIを戻工
噸宥のWEBアプリにえる採か
夛
PostgreSQLに徨プロセスで岷俊リスニングさせる
PL/Pythonを聞喘
Pythonの を旋喘bottoleフレ`ムワ`ク
インデント圻尖麼x
2狼と3狼があって^局豚
C亠僥とかy僥で恷除よくる
def?say_hello():
????for?i?in?range(1,100):
????????print?"HELLO?No?%s!"?%?i
PL/Python
create extensionで弖紗
PythonをPostgreSQLで聞える
plpyモジュ`ルでSQLもあつかえる
プレ`スホルダ`を聞ってg佩す
る栽
CREATE?FUNCTION?pystrip(x?text)
??RETURNS?text
AS?$$
target_query?=?"select?empno?from?emp?where?ename=$1"
plan?=?plpy.prepare(target_query,["text"])
r_set?=?plpy.execute(plan,?[?"SMITH"?])
return?r_set[0]["empno"]
$$?LANGUAGE?plpythonu?
岷俊g佩する栽
CREATE?FUNCTION?pl_py_test(x?text)
??RETURNS?text
AS?$$
r_set?=?plpy.execute("select?empno?from?emp?where?ename='SMITH'")
return?r_set[0]["empno"]
$$?LANGUAGE?plpythonu?
PythonのWEBフレ`ムワ`ク
1ファイルに畠てが根まれる
恷X楚
PG2LAYER 撹
でも2夛
graph LR id1(クライアント:
ブラウザ)-->id2(DBサ`バ:
ロジック) style id1 fill:#955,stroke:#111,stroke-width:4px; style id2
fill:#555,stroke:#111,stroke-width:4px;
詰卆贋來 (bottole.py /DBLINK / ドライバ音勣)
詰レイヤ` (ブラウザ <-> デ`タベ`ス)
詰砿尖コスト (DBのバックアップ = APのバックアップ, htmlファイル
レス)
軟
聞喘ポ`トを哈方にしてファンクションを軟咾垢襪世
pg2layer_db=#?select?start_bottole_httpd(1192)?
ソ`ス
CREATE?OR?REPLACE?FUNCTION?start_bottole_httpd(v_port?integer)?RETURNS?text?AS
$$
"""
PG2LAYER????PostgreSQL?Two?Layer?Management?System
*?Low?dependency?(?only?bottole.py?,?only?dblink)
*?Low?layer?(browser?<?>?DB,?never?AppServer?or?HTTP?Server)
*?Low?manage?cost?(?backup?database?backup?the?Web?App)
It's?Joke?Web?App.
2015/05?sayamada
"""
import?sys
import?os
import?json
import?signal
#?$PGDATA塘和に塘崔したbottole.pyをPYTHONPATHに弖紗しないといけないので
sys.path.append(os.getcwd()+"/PL_Python_Httpd")
from?bottle?import?route,?run,?template,?response,?request,?get,?post,?redirect
#?for?DBLINK
DB_NAME?=?"pg2layer_db"
DB_USER?=?"sayamada"
DB_HOST?=?"localhost"
api(select_list,table_name,where_col=None,col=None,col_val=None):
URLからクエリを伏撹しJSONのレスポンスをす
static(content_type,file_name):
床議なソ`ス(css/js吉)をす
床議ファイルは燕デ`タとして鯉{
get_tmplt(tmplt_name=None):
bottoleのテンプレ`トファイルをす
ほぼHTML
燕デ`タとして鯉{
do_query_over_dblink(v_query_string):
DBLIKU喇でSQLI尖しJSONです(瘁峰)
edit():
POSTリクエストに児づきテンプレ`トを厚仟
1rg
恬撹1晩(のはずが1Lg)
はまったところ
(きっと徭蛍だけ)
}その1
ImportError: No module named bottole
カレントに塘崔したbottole.pyがiみzめない
噸宥はカレントディレクトリは峺協しなくてもいい
PostgreSQLの徨プロセスは$PGDATAがカレント
pg2layer_db=#?CREATE?OR?REPLACE?FUNCTION?test()?RETURNS?text?AS
pg2layer_db?#?$$
pg2layer_db$#?
pg2layer_db$#?import?bottole
pg2layer_db$#?$$
pg2layer_db?#?LANGUAGE?'plpythonu'?VOLATILE?
CREATE?FUNCTION
pg2layer_db=#?
pg2layer_db=#?select?test()?
ERROR:??ImportError:?No?module?named?bottole?
CONTEXT:??Traceback?(most?recent?call?last):
??PL/Python?function?"test",?line?3,?in?<module>
????import?bottole
PL/Python?function?"test"
圻咀
PYTHONPATHに$PGDATAが根まれていない
javaのCLASSPATHとかLD_LIBRARY_PATH議なもの
ライブラリをiみzむディレクトリ
I
AP坪で啜弔$PGDATA塘和をPYTHONPATH
に弖紗
import?sys
#?$PGDATA塘和に塘崔したbottole.pyをPYTHONPATHに弖紗
sys.path.append(os.getcwd()+"/PL_Python_Httpd")
}その2
トランザクションがCommitできない
HTMLソ`スシC嬬を弖紗
フォ`ムからPOSTしたら郡啌はされる
PG2LAYERが械K阻したら筝デ`タがる(!?)
PL/Pythonでトランザクション砿尖
をしてもだめだった(というかcommitないし)
43.8. 苧幣議サブトランザクション
圻咀
柵び竃し圷のstart_bottole_httpdファンクションがK阻しないから
佩った筝はstart_bottole_httpdを屎械唯峭させない泙rollback
I
DBLINKで徭舵侏トランザクション
DBLINKでル`プバックして徭舵侏トランザクションで
????base_query?=?"SELECT?*?FROM?dblink('host=%s?port=%s?dbname=%s?user=%s',%s)?AS?t(r?text)"
????target_query?=?"update?pg_2_template?set?src=/slideshow/201505-postgresqlplpythonweb/48970892/%s?where?file_name=%s?returning?file_name"?%?(
????????????????????????????????????????????????plpy.quote_literal(edit_src),
????????????????????????????????????????????????plpy.quote_literal(edit_file_name)
????????????????????????????????????????????)
????last_query?=?base_query?%?(
????????DB_HOST,
????????DB_PORT,
????????DB_NAME,
????????DB_USER,
????????plpy.quote_literal(target_query)
????)
????r_set?=?plpy.execute(last_query)
}3
借喀yが吭蹐擦砕iみ函り匯來をk]
api()v方でk伏
pg_stat_activity吉がstart_bottole_httpd軟r泣のY惚しかとれない
repetable read 議な
噸宥の燕はちゃんとread commited
圻咀
音苧(謹蛍}2と揖じ?)
I
DBLINK
借喀y狼だけ蛍けるもの中宜なのでAPIは畠何DBLINKU喇に筝
}4
DBLINKU喇のクエリで双リストが音協
APIでは双リストをURLで峺協するg廾
url query
/api/*/hoge -> select * from hoge
/api/col1,col2/hoge -> select col1,col2 from hoge
DBLINKはり、離禰`タ侏を苧幣しないといけない
I
そうだJSONにしよう
圷クエリをjson_aggでラップ
り、呂ならずJSON
dblink('dbname=pg_2_layer', 'select json_agg(t) from (圷クエリ) t')
AS t(result json)
#?DBLINKで徭舵侏トランザクションとする
#?侏にしばられないため、json_aggでラップしている
#?りは畠何JSON
def?do_query_over_dblink(v_query_string):
????#?DBLINKの寄
????base_query?=?"SELECT?*?FROM?dblink('host=%s?port=%s?dbname=%s?user=%s',?%s)?AS?t(result?json)
????last_query?=?base_query?%?(
????????DB_HOST,
????????DB_PORT,
????????DB_NAME,
????????DB_USER,
????????plpy.quote_literal("select?json_agg(t)?from?("?+?v_query_string+?")?t")?#?クエリも哈方なので
????)
????plpy.log(?last_query)
????r_set?=?plpy.execute(last_query)
????plpy.log(r_set)
????#?jsonでしても函誼rはstrになってたのでstrとしてy匯
????result_json_str?=?"[]"
????if?r_set[0]["result"]?is?not?None:
????????result_json_str?=?r_set[0]["result"]
????#?旋喘箸寮宴來を深えてjsonです
圷のクエリを
select?*?from?emp
json_aggでラップして
select?json_agg(t)?from?(
????select?*?from?emp
)?t
dblinkでラップする
select?*?from?dblink('
????select?json_agg(t)?json?from?(
????????select?*?from?emp
????)?t'
)?AS?t(result?json)
こんだけラップで採がパフォ`マ
ンスか
}5
唯峭できない
start_bottole_httpdが峭められない
ctrl+c/pg_terminate_backendできず
ctrl+c
pg2layer_db=#?select?start_bottole_httpd(1192)?
^CCancel?request?sent
ctrl+c
pg2layer_db=#?select?start_bottole_httpd(1192)?
^CCancel?request?sent
^CCancel?request?sent
ctrl+c
pg2layer_db=#?select?start_bottole_httpd(1192)?
^CCancel?request?sent
^CCancel?request?sent
^CCancel?request?sent
ctrl+c
pg2layer_db=#?select?start_bottole_httpd(1192)?
^CCancel?request?sent
^CCancel?request?sent
^CCancel?request?sent
^CCancel?request?sent
鯛ちない看姻噛
圻咀
g佩嶄はpostgresqlのコンテキストではなくPythonのコンテキスト
シグナルハンドラがPythonコンテキストで嘛してない?
I
徭蛍でシグナルハンドラく
PythonコンテキストでSIGINTをI尖するように
鞭け函ったら鯛ちる
def?signal_handler(num,?frame):
????plpy.log("SIGINT_restart")
????sys.exit(0)
signal.signal(signal.SIGINT,?signal_handler)
run(host='0.0.0.0',?port=v_port)
いないと房いますが
PL/Pythonを聞ったWEBアプリを恬撹されようと房っている圭の
匯廁になれば侑いです。
嶮わり

More Related Content

201505 PostgreSQLアンカンファレンス(PL/Pythonで恬るWEBアプリ)