money型の変更二題

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

今日は[PGCONF.Asia 2017のDay-0 Unconference](http://www.pgconf.asia/JA/2017/day-0-developer-unconference/)。PostgreSQLの開発者たちが熱い議論を繰り広げるんじゃないかと思います。自分は今のところ開発者じゃないので出席できませんが。

今日はちょい地味目のネタですまんな。
# money型
PostgreSQLにはいろいろな型があるのですが、その1つが[money型](https://www.postgresql.jp/document/9.6/html/datatype-money.html)だ。
名前のとおり通貨を管理する型なんだけど、今ひとつ日本では使われていない気もする。
この型は、内部的にはbigint(int8)で管理しているっぽい。で、外部表現では小数点2桁まで管理している。

|型|値域|
|:--|:--|
|bigint|-9223372036854775808から+9223372036854775807|
|money |-92233720368547758.08 から +92233720368547758.07|

小数2桁、というのはドルとセントを管理するためなのかな。
まあ、日本だと原則「円」単位なので、今ひとつ使う意義がないかも。

あと、money型はロケール(lc_monetary)設定によって出力形式が変わるという特徴がある。
（今日はロケールの話はしない。悪しからず）

# PostgreSQL 10の改善点 その1
money型に対して、int8型で乗算/除算する演算子が追加された。

以前、[PostgreSQLのデータ型で使用可能な演算子の一覧を表示する](https://qiita.com/nuko_yokohama/items/d0e49f8b5877cb0f7d32)というのを調べたことがあったので、そのクエリを使ってみる。

## PostgreSQL 9.6まで

```postgres-console
money=# SELECT 
  o.oprname, t1.typname AS lefttype, t2.typname AS righttype 
FROM pg_operator o, pg_type t1, pg_type t2 
WHERE t1.typname = 'money' AND (t1.oid = o.oprleft AND t2.oid = o.oprright);
 oprname | lefttype | righttype 
---------+----------+-----------
 *       | money    | float4
 /       | money    | float4
 =       | money    | money
 <>      | money    | money
 <       | money    | money
 >       | money    | money
 <=      | money    | money
 >=      | money    | money
 +       | money    | money
 -       | money    | money
 *       | money    | float8
 /       | money    | float8
 *       | money    | int4
 /       | money    | int4
 *       | money    | int2
 /       | money    | int2
 /       | money    | money
(17 rows)
```
int8による乗算(*)と除算(/)の演算子は存在しない。

## PostgreSQL 10でこう変わった。

```postgres-console
money=# SELECT 
  o.oprname, t1.typname AS lefttype, t2.typname AS righttype 
FROM pg_operator o, pg_type t1, pg_type t2 
WHERE t1.typname = 'money' AND (t1.oid = o.oprleft AND t2.oid = o.oprright);
 oprname | lefttype | righttype 
---------+----------+-----------
 *       | money    | int8
 *       | money    | int2
 *       | money    | int4
 *       | money    | float4
 *       | money    | float8
 +       | money    | money
 -       | money    | money
 /       | money    | int8
 /       | money    | int2
 /       | money    | int4
 /       | money    | float4
 /       | money    | float8
 /       | money    | money
 <       | money    | money
 <=      | money    | money
 <>      | money    | money
 =       | money    | money
 >       | money    | money
 >=      | money    | money
(19 rows)
```
うむ。たしかにint8による乗算(*)と除算(/)の演算子が追加されている。

# PostgreSQL 10の改善点 その2
## PostgreSQL 9.6まで
一部の入力パターンに関してオーバーフローのチェックがされず、不正な値として評価されていた。

こういうパターンはOK。

```postgres-console
money=# SELECT 100000000000000000::money;
ERROR:  bigint out of range
```
しかし、数字文字列をキャストするようなケースはオーバーフローチェックされず、意図しない値で評価されてしまう。

```postgres-console
money=# SELECT '100000000000000000'::money;
            money            
-----------------------------
 -$84,467,440,737,095,516.16
(1 row)
```

## PostgreSQL 10でこう変わった。
PostgreSQL 10では数字文字列のケースでもきちんとオーバーフローチェックをしてくれる。
機能改善というよりバグFixに近い修正かな。

```postgres-console
money=# SELECT '100000000000000000'::money;
ERROR:  value "100000000000000000" is out of range for type money
LINE 1: SELECT '100000000000000000'::money;
               ^
```

# おわりに
![100000000000000000ほしい.png](https://qiita-image-store.s3.amazonaws.com/0/32626/be27dede-7f15-2619-1530-1a4969f9c4ff.png)


# 参考：該当するリリースノート
本エントリに関連するPostgreSQL 10リリースノートの記載です。

E.2.3.5. Data Types

> * Add operators for multiplication and division of money values with int8 values (Peter Eisentraut)
> * Check for overflow in the money type's input function (Peter Eisentraut)