Linuxコマンドをfile_fdwの入力として使う。

# はじめに
にゃーん
この記事は、[PostgreSQL 10全部ぬこ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/pg10-nuko-only) の2日目のエントリです。

# file_fdwってなんぞ？
FDWというのはForeign Data Wrapperのことで、PostgreSQLのテーブルじゃないものをテーブルとして扱える、PostgreSQLの素敵機能の一つ。いろんな種類のFDWが既に存在していますが、file_fdwはPostgreSQLのcontribモジュールとして提供されているもの。
[file_fdw](https://www.postgresql.org/docs/10/static/release-10.html)というのは、簡単に言うと、CSVファイルなどのファイルをテーブルのように参照できるFDWです。これは、PostgreSQL 9.3から使用可能です。

# PostgreSQLで追加された機能
リリースノートや、contrib/file_fdwの文書を見る限り、optionにprogramが指定されただけっぽい。programを使った例が載っていないあたりが、PostgreSQL文書クオリティではあるｗ

# df コマンドの結果をfile_fdw経由で参照する。
この機能、たぶんLinux上のOSコマンドやシェルの結果をテーブルとして扱えるようにする、というものだろう。
たとえば、CSVファイルを ```cat /tmp/foo.csv```とか書いてあげれば、filename指定と同等のことができるようになるんだろう。

それじゃ面白くないので、ちょっと役に立ちそうな例を考えてみる。
Linuxには```df```コマンドというのがある。ご存知、ディスクの残容量やファイルシステムタイプを表示するコマンドだ。PostgreSQLの運用監視時にも、このコマンドを使うことはあると思う。

## file_fdwのインストール
file_fdwはコア機能ではなく、contribモジュールなので、ソースからビルド＆インストールするか、あるいはyum/RPMでcontribパッケージを別途インストールする必要がある。具体的な手順は省略。

## file_fdwの登録
file_fdwはデータベースに対してCREATE EXTENSIONして使う必要がある。こんな感じ。

```
[nuko@localhost ~]$ psql -U postgres fdw -c "CREATE EXTENSION file_fdw"
CREATE EXTENSION
[nuko@localhost ~]$ psql -U postgres fdw -c "\dx file_fdw"
                      List of installed extensions
   Name   | Version | Schema |                Description                
----------+---------+--------+-------------------------------------------
 file_fdw | 1.0     | public | foreign-data wrapper for flat file access
(1 row)
```

## 外部サーバと外部テーブルの登録
まず、外部サーバを登録する。特にOPTINOSはつけなくてもよろし。

```postgres-console
fdw=# CREATE SERVER os_cmd FOREIGN DATA WRAPPER file_fdw;
CREATE SERVER
fdw=#
```

次に外部テーブルを登録する。今回作成する外部テーブルでは、以下のdfコマンドをawkを使って整形(ヘッダ行を削除して、ファイルシステム名、ファイルシステムタイプ、総容量、使用量、残量、マウント先をタブ区切りで表示)するというもの。

```postgres-console
fdw=# CREATE FOREIGN TABLE df (name text, type text, total int, used int, remaining int, mount text) 
  SERVER os_cmd
  OPTIONS (program 'df -T | awk ''{if (NR != 1) {printf ("%s\t%s\t%d\t%d\t%d\t%s\n", $1,$2,$3, $4,$5,$7)}}'' ');
```

## 実行
あとは、このdfテーブルに対してSELECT文を実行すればOK。

```postgres-console
fdw=# SELECT * FROM df;
          name           |   type   |  total   |   used   | remaining |     mount      
-------------------------+----------+----------+----------+-----------+----------------
 /dev/mapper/centos-root | xfs      | 18348032 | 16180384 |   2167648 | /
 devtmpfs                | devtmpfs |  2445076 |        0 |   2445076 | /dev
 tmpfs                   | tmpfs    |  2454364 |   624244 |   1830120 | /dev/shm
 tmpfs                   | tmpfs    |  2454364 |    31636 |   2422728 | /run
 tmpfs                   | tmpfs    |  2454364 |        0 |   2454364 | /sys/fs/cgroup
 /dev/sda1               | xfs      |   508588 |   121304 |    387284 | /boot
(6 rows)
```

やったね♪
あとはSELECT文を使って好きフィルタかけたりソートしたり集約したり、自由に検索できる。

つーか、俺の検証環境・・・
![うわっ私のVM環境.png](https://qiita-image-store.s3.amazonaws.com/0/32626/423a58a0-91a8-12ad-6dd2-e5d5f4507aa8.png)

# まとめ
この機能、一見地味ではあるけど、LinuxのOS情報の監視にSQL文が使える＝別サーバからデータベース・サーバのOS情報の監視も簡単にできるようになるのは大きい。
監視エージェントをPostgreSQLサーバに入れなくてもいいというのは、意外と監視方式の大きな変革になりそうな気もしてきた。

でも、たぶんAWS RDS/Auroraではこの機能はブロックされているだろうなあ・・・(´・ω・`)

# 該当のリリースノート

E.2.3.12. Additional Modules

> * Allow file_fdw to read from program output as well as files (Corey Huinker, Adam Gomaa)