PostgreSQL開発の基本動作まとめ

インドからの投稿です。

PostgreSQL開発や、PostgreSQLコミュニティに入るために有用な情報が書いてあるスライドが幾つかありますが、記事としてはあまりないように思ったので、PostgreSQLコミュニティに参画し開発、レビューする上での必要な様々な基本動作をまとめます。

2015/11のPostgreSQL勉強会でもPostgreSQLコミュニティ開発について話したので、[そのときの資料](http://www.slideshare.net/hadoopxnttdata/patch-review-postgresql-community-nttdata?qid=52b99ee1-2129-48d2-97de-3c9dc15be76e&v=qf1&b=&from_search=2)もあわせてご参照ください。

# 必要なもの
* PC(Windows, Linux, Mac)
    * Mac上に仮想マシン立てたLinuxで開発したい場合、「VirtualBox + SSHで接続」で十分だと思います。
    * PostgreSQLをコンパイル、実行できる環境を用意します。
    * デバッガ(gdbなど)が入ってるとbetter。
* PostgreSQLのソースコード
    * 後述するgitからHEADを取得する方法でもOK。場合によっては特定のバージョンを取得してもOK。
* エディタ
    * Vim、Emacs、各種IDEなど
* ネット環境
    * ソースコード入手、メールぐらいなのでテザリングでも十分だと思います。

# 基本動作

## ソースコード入手から起動まで

PostgreSQLの公式Gitレポジトリは <git://git.postgresql.org/git/postgresql.git> です。
または、<http://www.postgresql.org/ftp/source/>から各バージョンのソースコードを入手、解凍します。

```
/* gitをつかって最新のソースコードを入手 */
$ git clone git://git.postgresql.org/git/postgresql.git
$ cd postgresql
$ ./configure --prefix=/home/hoge/pgsql/master --enable-debug --enable-cassert --enable-tap-tests CFLAGS=-O0
$ make -j 2
$ make install
/* ここまででインストール完了 */
$ cd /home/hoge/pgsql/master
$ bin/initdb -D data -E UTF8 --no-locale
$ bin/pg_ctl start -D data
/* ここまでで起動完了(起動ポートはデフォルトの5432) */
```

|オプション|意味|
|:-------:|:--:|
|--prefix=/home/...|PostgreSQLをインストールするパス|
|--enable-debug|デバッグシンボルを付けてコンパイル|
|--enable-cassert|Assertを有効にする|
|--enable-tap-tests|TAPテストを有効にするため。 PerlのIPC::Runモジュールが必要になります。|
|CFLAGS=-O0|デフォルトだと-O2でコンパイル時に最適化されてしまうので-O0に変更する。これもデバックのため。|

※`make -j 4`の`-j`はコンパイル時の多重度です。マルチコアマシンの場合は多重度を上げる事で、より　短い時間でコンパイル出来ます。

## 複数バージョン使う時
PostgreSQLを複数バージョン使うときには、以下のようなディレクトリ構成にすると管理が楽です。

```
/home/hoge
   └ pgsql
      ├ 9.4.5                   ← --prefixオプションで指定するパス
      │  ├ postgresql-9.4.5     ← ソースコード本体
      │  │  ├ src
      │  │  ├ doc
      │  │  :
      │  ├ data                 ← データベースクラスタ
      │  ├ bin
      │  ├ include
      │  ├ lib
      │  └ share
      ├ master                  ← --prefixオプションで指定するパス
      │  ├ postgresql           ← ソースコード本体
      │  │  ├ src
      │  │  ├ doc
      │  │  :
      │  ├ data                 ← データベースクラスタ(initdbコマンドで指定)
      │  ├ bin
      │  ├ include
      │  ├ lib
      │  └ share
      :
```

また、複数バージョンのPostgreSQLを起動するときはポート番号を

* バージョン9.4.5 -> 5945番ポート
* バージョン9.3.2 -> 5932番ポート
* gitから取得したHEAD -> 5432番ポート(デフォルト)

のようにポート番号とバージョン関連付けると管理が楽です。

ポート番号だけ変えて起動したいのであれば、postgresql.confを編集しなくても
`$ pg_ctl start -D data -o "-p 5945"` でポート番号を変えて起動出来ます。

## ソースコードの閲覧

ソースコードはエディタで見るのがいいと思います。
ただし、ネット経由でも<http://doxygen.postgresql.org>でHEADのソースコードが見れます。
以下はEmacsを使ったタグジャンプの例です。

```bash
/* タグジャンプの設定 */
$ cd <ソースコードのトップディレクトリに移動>
$ sh src/tools/make_stags
```

あとは、Emacsを起動して`M-.`を入力し、ジャンプしたい関数、変数名を入力すればジャンプできます。


# パッチレビュー & 機能開発

まずは [こちら](http://www.slideshare.net/hadoopxnttdata/patch-review-postgresql-community-nttdata?qid=52b99ee1-2129-48d2-97de-3c9dc15be76e&v=qf1&b=&from_search=2) の資料をご覧ください。パッチレビューとは、パッチレビューのやり方などを記載しています。

## パッチのあて方

```bash
$ cd <ソースコードのトップディレクトリに移動>
$ patch -d. < /tmp/new_feature.patch
または
$ git apply /tmp/new_feature.patch
```

※ patchコマンドは変更できる箇所はすべて適用、git applyは全部正常に適用できる場合にのみ変更を適用。


## git操作

* ソースコードを最新の状態にする
`$ git pull origin master`

* 新しい機能を作るためにブランチを切る
`$ git checkout -b new_feature`

* 現在のブランチを確認する
`$ git branch -v`

* 現在のブランチを切り替える
`$ git checkout new_feature`

* これまで加えたソースコードの変更を元に戻す(HEADまで)
`$ git reset --hard HEAD`

* ある行がどのコミットで変更されたかを確認するとき
` $ git blame src/backend/replication/syncrep.c`

* 特定のブランチのdiffを出力する(new_featureブランチで新しい機能を作り、そのパッチを作成するときに使います)

```bash
$ git checkout new_feature
$ git diff master
/* パッチを作成するときは以下のようにします */
$ git diff master > new_feature.patch
```

##リグレッションテスト

PostgreSQLにはリグレッションテストの機能が備わっているのでそれを利用します。
以下は、PostgreSQLの全機能(Contribモジュールも含む)についてリグレッションテストを多重度4で実行する例です。(実行ログをあとで確認するためにteeコマンドを利用しています)

```
$ cd <ソースコードトップディレクトリへ移動>
$ make check-world -j 4 | tee /tmp/check-world.log
$ less /tmp/check-world.log
/* FAILEDなどのキーワードを探してテストの結果をチェックします */
```

* リグレッションテストの種類

|目的|手順|備考|
|:-:|:---:|:--:|
|PostgreSQL本体 + Contribモジュール|`$ make check-world`|-|
|PostgreSQL本体のみ| `$ make check`|-|
|PostgreSQLのクライアントツール(psqlやpg_dumpのみ)|src/binに移動して`$ make check`。または、`$ make check -C src/bin`|特定のツールのみをテストしたい場合はそのディレクトリ移動して`make check`。または-Cでディレクトリを指定する。|
|PostgreSQLのContribモジュール|contribディレクトリに移動して`$ make check`または`$ make check -C contrib`|特定のContribモジュールのみをテストしたい場合はそのディレクトリ移動して`make check`。または-Cでディレクトリを指定する。|

※ リグレッションテストでも`make check -j 3`とすることで、多重度を上げて実行することが可能です。

## デバッグ
Emacsの場合、Emacs + gdbでデバッグすることでソースコードを見ながら効率よくデバッグが可能です。

以下は起動済みのPostgreSQLのサーバプロセスにアタッチし、デバッグする手順です。２つのターミナルを使います。

* ターミナルA : サーバへ接続し、SQLを入力。
* ターミナルB : Emacs+gdbを起動しデバッグ。

```bash:ターミナルA
/* 事前にPostgreSQLサーバを起動しておきます */
$ psql -d postgres
psql (9.6devel)
Type "help" for help.

postgres(1)=# 
```

```bash:ターミナルB
/* サーバプロセスのpidを確認します。以下の例だと5145がアタッチするプロセスです。 */
$ ps x | grep postgres
 5122 pts/7    S      0:00 /home/masahiko/pgsql/master/bin/postgres -D data
 5124 ?        Ss     0:00 postgres: checkpointer process                  
 5125 ?        Ss     0:00 postgres: writer process                        
 5126 ?        Ss     0:00 postgres: wal writer process                    
 5127 ?        Ss     0:00 postgres: autovacuum launcher process           
 5128 ?        Ss     0:00 postgres: stats collector process               
 5144 pts/7    S+     0:00 bin/psql -d postgres
 5145 ?        Ss     0:00 postgres: masahiko postgres [local] idle        
 5221 pts/9    S+     0:00 grep postgres

/* Emacsを起動。-nwオプションをつけることでターミナル内でEmacsが起動可能。*/
$ emacs -nw
「M-x gdb」を入力し、
「Run gdb (like this): gdb --annotate=3」　と出たら、
「Run gdb (like this): gdb --annotate=3 attach 5145」　と入力しEnter。
以降は、gdbのコマンドを使用してデバッグを行います。
```

# メール

既存のメールアドレスを利用してもOK。新しくコミュニティ開発用のgmailアカウントを作成してもOK。

MLの登録は、http://www.postgresql.org/community/lists/subscribe/ から。

* pgsql-hackers
* pgsql-bugs
* pgsql-general
* pgsql-committers

に登録します。
メールを書くときのポイントも[こちら](http://www.slideshare.net/hadoopxnttdata/patch-review-postgresql-community-nttdata?qid=52b99ee1-2129-48d2-97de-3c9dc15be76e&v=qf1&b=&from_search=2) の資料に記載しています。
この他にも、

* 英語のコメントや issue で頻出する略語の意味 (FYI, AFAIK, ...)
    * http://qiita.com/uasi/items/86c3a09d17792ab62dfe

# Commit Fest

Commit Festについては[こちら(Wiki)](https://wiki.postgresql.org/wiki/CommitFest)
Commit Festのリンクは[こちら](https://commitfest.postgresql.org)

* Commit Festのステータス一覧

|種類|ステータス|意味|備考|
|:---:|:------:|:--:|:-----:|
|Active|Needs Review|レビュー待ちのパッチ|-|
|Active|Waiting on Author|パッチ作者の修正・更新待ち|-|
|Active|Ready for Committer|コミッターのコミット待ち|レビュワーの仕事は終了|
|Close|Committed|コミット済み|-|
|Close|Move on next CF|次のCFへ|レビューの時間が足りない場合になる時が多いです|
|Close|Rejected|提案却下|以降のCFで再度提案してもたぶん受け入れられません|
|Close|Returned with Feedback|課題あり|議論中に何か課題があり、それが解決ししたら再提案します|

レビューするパッチは「Needs Review」のものから選ぶと取り掛かりやすいです。

#関連資料へのリンク
* PostgreSQLコミュニティに飛び込もう
    * <http://www.slideshare.net/hadoopxnttdata/patch-review-postgresql-community-nttdata?qid=52b99ee1-2129-48d2-97de-3c9dc15be76e&v=qf1&b=&from_search=2>
* PostgreSQLハッキング　最初の一歩
    * https://www.slideshare.net/secret/t4EBtDL4qyMZjG
* C言語によるユーザ定義関数の作り方
    * http://www.slideshare.net/snaga/how-towritepgfunc
* PostgreSQL開発ことはじめ
    * http://www.slideshare.net/babystarmonja/postgresqlhackers-champloo-2014

以上、PostgreSQL開発における基本動作のまとめでした。ぜひPostgreSQLコミュニティに参画してみてください！
JPUG主催「PostgreSQL newbie hackathon(仮)」も2016年2,3月あたりに現在計画中のようです。

明日の PostgreSQL Advent Calender の担当は [syobochim](http://qiita.com/syobochim) さんです。よろしくお願いします。