LoginSignup
6
4

More than 5 years have passed since last update.

money型の変更二題

Last updated at Posted at 2017-12-03

はじめに

にゃーん
この記事は、PostgreSQL 10全部ぬこ Advent Calendar 2017 の4日目のエントリです。

今日はPGCONF.Asia 2017のDay-0 Unconference。PostgreSQLの開発者たちが熱い議論を繰り広げるんじゃないかと思います。自分は今のところ開発者じゃないので出席できませんが。

今日はちょい地味目のネタですまんな。

money型

PostgreSQLにはいろいろな型があるのですが、その1つがmoney型だ。
名前のとおり通貨を管理する型なんだけど、今ひとつ日本では使われていない気もする。
この型は、内部的にはbigint(int8)で管理しているっぽい。で、外部表現では小数点2桁まで管理している。

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

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

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

PostgreSQL 10の改善点 その1

money型に対して、int8型で乗算/除算する演算子が追加された。

以前、PostgreSQLのデータ型で使用可能な演算子の一覧を表示するというのを調べたことがあったので、そのクエリを使ってみる。

PostgreSQL 9.6まで

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でこう変わった。

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。

money=# SELECT 100000000000000000::money;
ERROR:  bigint out of range

しかし、数字文字列をキャストするようなケースはオーバーフローチェックされず、意図しない値で評価されてしまう。

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

PostgreSQL 10でこう変わった。

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

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

おわりに

100000000000000000ほしい.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)
6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4