PostgreSQLへ各種言語から繋ぎたい

この記事は[PostgreSQL Advent Calendar 2015](http://qiita.com/advent-calendar/2015/postgresql) の4日目です。3日目は[kasa_zip様](http://lets.postgresql.jp/documents/technical/lateral/1)でした。

ここ数年、データ分析の分野が大変賑わっています。大規模となるとSpark/Hadoopのあたりが必要かもしれませんが、ある程度の規模であればRDBMSで十分対応できます。特にPostgreSQLはJSONサポートも豊富ですので、中規模までの分析基盤であれば十分ではないでしょうか。

ということで、各言語からPostgreSQLに接続するためのドライバ・モジュールを整理してみます。  
※JavaとPython以外が薄いのはあまり触ってないからです…

## Javaの場合

PostgerSQL JDBCドライバが提供されていますので、こちらを使いましょう。
[download](https://jdbc.postgresql.org/download.html)

![jdbc.png](https://qiita-image-store.s3.amazonaws.com/0/44722/78b47aae-8518-ec80-4dbb-e4f0f2fb33dc.png)

使用するJDBCドライバを選ぶときは、実行環境のJDKのバージョンを元に選びます。例えばJDK 1.8の場合はJDBC42のドライバが必要になるので、9.4 build 1202-1206の何れかを使用します。PostgreSQLの通信プロトコルは[7.4以降共通のため](https://www.postgresql.jp/document/9.4/html/protocol.html)、9.4のドライバを使用しても7.4以降のPostgreSQLへ接続することは何ら問題ありません。利用するJDKに対応した最新のドライバを使用すればよいでしょう。

なお、PostgreSQLのJDBCドライバはPure Javaのためlibpqを必要とせず、単体で動作しますのでダウンロードしたドライバのみCLASSPATHに追加すればよいでしょう。

## Pythonの場合

Pythonの場合は、[PostgreSQL wiki](https://wiki.postgresql.org/wiki/Python)にまとまっています。
![jdbc1.png](https://qiita-image-store.s3.amazonaws.com/0/44722/42540447-205b-3300-6ba5-52a5e7c3b5ad.png)

表にもありますが、Pythonでは複数のドライバが提供されています。割と名前をよく耳にするのは以下の3つあたりでしょうか。

* [psycopg2:先月DL数(718640)](https://pypi.python.org/pypi/psycopg2)
* [pg8000:先月DL数(46977)](https://pypi.python.org/pypi/pg8000)
* [py-postgresql:先月DL数(3339)](https://pypi.python.org/pypi/py-postgresql)

DL数を見るとpyscopg2が圧倒的です。実際、利用実績も多いですし、Python2/3系ともに対応しているので使いやすいです。ただし、psycopg2は**libpq**に依存していますので、postgresql-devel等パッケージが必要です。

一方で、pg8000やpy-postgresqlはPure Pythonで実装されていますので、libpqを必要としません。その点では導入コストが低いですが、<del>**pg8000**は**Python2系**のみ</del>**py-postgresql**は**Python3系のみ**をサポートしている点に注意してください。
※py-postgresqlのDL数が少ないのはPython3系のユーザ自体が現状少ないことも影響している模様です。

簡単なツール類であれば、PurePythonのドライバのほうが容易ですが、安定性等を考慮しますと**psycopg2**を利用するのが安心かと思われます。

なお、余談ですが@snaga様が公開されている[postgres-toolkit](https://github.com/uptimejp/postgres-toolkit/)の内部では、[PsqlWrapper.py](https://github.com/uptimejp/postgres-toolkit/blob/develop/lib/PsqlWrapper.py)という名前でpsql経由でSQLを発行しつつ、標準出力を扱いやすい形にパースして戻すライブラリを実装されています。個人的にPostgreSQLで処理をする軽量ツールを作成する場合は、このような実装を行なうことも選択肢の一つかもしれません。

## Node.jsの場合

Node.jsでPostgreSQLに接続する場合は[node-postgres](https://github.com/brianc/node-postgres)を使うことが多いです。こちらはPure Javascriptの実装ですので、以下でインストール可能です。

```
$ npm install pg
```

なお、node-postgresにはlibpqを利用する**pg-native**もありますが、多くの場合は**pg**で利用されているようです。
node-postgresでは、取得結果をJSON形式で戻しています。

```json
[
    {
        "empno": "7369",
        "ename": "SMITH",
        "job": "CLERK",
        "mgr": "7902",
        "hiredate": "1980-12-17T00:00:00.000Z",
        "sal": "800.00",
        "comm": null,
        "deptno": "20"
    },
    {
        "empno": "7499",
        "ename": "ALLEN",
        "job": "SALESMAN",
        "mgr": "7698",
        "hiredate": "1981-02-20T00:00:00.000Z",
        "sal": "1600.00",
        "comm": "300.00",
        "deptno": "30"
    }
]
```
なかなか直感的な形式ですが、さらに9.1以降で追加されている[JSON型](https://www.postgresql.jp/document/9.4/html/datatype-json.html)やJSONB型も以下のようにしれっとJSONとして戻してくれます。

```sql
sample_db=# create table json_test(json_col json);
CREATE TABLE
sample_db=# insert into json_test values('{"A":{"B":[1,2,3]}}'::json);
INSERT 0 1
sample_db=# insert into json_test values('{"C":{"D":[4,5]}}'::json);
INSERT 0 1

```

```json
[
    {
        "json_col": {
            "A": {
                "B": [
                    1,
                    2,
                    3
                ]
            }
        }
    },
    {
        "json_col": {
            "C": {
                "D": [
                    4,
                    5
                ]
            }
        }
    }
]
```

Node.jsというとバックエンドはMongoDBなケースも多いですが、PostgreSQLも十分にNode.js向きではないでしょうか。


## .NET Frameworkの場合

[Npgsql](http://www.npgsql.org/)を利用することで、.NETからもPostgreSQLに接続可能です。[Nuget経由で入手](https://www.nuget.org/packages/Npgsql/)できます。NpgsqlはPure C#なので、libpqを必要としません。Windows環境ではちょっとPostgreSQLの準備が面倒な時もあるので、これは嬉しいですね。

 ADO.NET互換なので、他のDBでADO.NETを使用したことがあれば殆ど迷うこと無く利用できるかと思います。

ちなみに、[Mono](http://www.mono-project.com/)でも動かせるようですが私は試したことがありません…


## PHPの場合

phpは[PostgreSQL関数](http://php.net/manual/ja/ref.pgsql.php)が用意されているため、こちらを利用することになります。なお、使用するにはphpが**—with-pgsql**オプション付きでコンパイルされている必要があります。また、[PDO](http://php.net/manual/ja/ref.pdo-pgsql.php)経由で使用する場合は**—with-pdo-pgsql**が必要です。libpqに依存していますので、postgresql-develなどのパッケージを別途導入する必要があります。

すでに導入されているPHPでPostgreSQL関数やPDO経由でPostgreSQLが利用できるかは、``<?php phpinfo() ?>``を使って確認できます。

また、**php-config**からコンパイルオプションを確認してもよいでしょう。


```bash:実行例
$ ./php-config --configure-options
--prefix=/home/sample/apps/php ...--with-pgsql=/home/sample/posgrehome --with-pdo-pgsql=/home/sample/posgrehome 
```


## Rubyの場合

Rubyは[ruby-pg](https://rubygems.org/gems/pg)モジュールをを利用することが多いようです。こちらもlibpqを使用する実装のようですのでpostgresql-develなどのパッケージを別途導入する必要があります。

```bash
gem install pg
```

なお、PostgreSQLをソースからビルドしているなどで通常とは異なるディレクトリにインストールして、ruby-pgのインストール時にコケます。その場合は以下のように**pg_config**へのパスを指定します。(マニュアルにも書いてあります)

```bash
gem install pg -- --with-pg-config=<path to pg_config>
```


## さいごに

ざっくりとではありますが、PostgreSQLを各種言語から利用する場合の話をまとめさせていただきました。主要な言語にはドライバがひと通り揃っていますので、まだPostgreSQLを利用されたことのない方は一度触ってみては如何でしょうか。

PostgreSQL Advent Calendar 2015 Day5の担当はnuko_yokohama様です。