目的
PostgreSQL11以降ではストアードプロシージャ利用できるようになります。ストアードプロシージャはストアードファンクションとは違ってリターンで値を返すことができません。しかしINOUTパラメーターで呼び出し側に結果を返すことができます。
RustでどうやってINOUTを受け取ることができるのか調べてみました。
結果、queryした戻りのrowsに1行だけ返ってきて、INOUTパラメーター名をカラムのように指定することで取得できることがわかりました。
コード
test_sp.sql
CREATE OR REPLACE PROCEDURE test_sp(
p_param BIGINT DEFAULT NULL
,INOUT p_result1 JSONB DEFAULT NULL
,INOUT p_result2 JSONB DEFAULT NULL
) AS $PROCEDURE$
DECLARE
BEGIN
p_result1 := jsonb_build_object(
'aaa',
'bbb',
'ccc',
p_param
);
p_result2 := jsonb_build_object(
'efg',
'hij',
'lmn',
p_param * 2
);
END;
$PROCEDURE$ LANGUAGE plpgsql;
Cargo.toml
[package]
name = "pg"
version = "0.1.0"
edition = "2018"
[dependencies]
serde_json = "^1.0"
r2d2_postgres = "^0.14"
[dependencies.postgres]
version = "^0.15"
features = [
"with-serde_json",
]
main.rs
fn main() {
let manager = r2d2_postgres::PostgresConnectionManager::new(
"postgres://localhost:5432/test",
r2d2_postgres::TlsMode::None).unwrap();
let pool = r2d2_postgres::r2d2::Pool::new(manager).unwrap();
let conn = pool.get().unwrap();
let sql = r#"
CALL test_sp(p_param := $1)
"#;
let param: i64 = 10;
let stmt = conn.prepare_cached(sql).unwrap();
let rows = stmt.query(&[¶m]).unwrap();
let row = rows.get(0);
let result: serde_json::Value = row.get("p_result1");
println!("{:?}", result);
let result: serde_json::Value = row.get("p_result2");
println!("{:?}", result);
}