int4range(1,5) = '[1,4]'::int4rangeはなぜ true なのか? PostgreSQLの勉強

range type について調べていたら「int4range(1,5) = '[1,4]'::int4range」がなぜtrueになるのかがわからず、週末を無駄にしてしまいました。翌日先輩に聞いたらあっさり解決したのですが、もしかしたら同じもやもやを抱えるかもしれない方のために備忘録を残します。

int4range(1,5) = '[1,4]'::int4range が true の理由

int4range(1,5) = '[1,4]'::int4range が true の理由を説明していきます。

なぜつまずいたか

range typeには閉じた境界、開いた境界というものがあり、[]は()には以下のような意味があります。

  • '[' = 以上
  • ']' = 以下
  • '(' = より大きい
  • ')' = 未満

そのため「int4range(1,5) = '[1,4]'::int4range」はfalseであり「int4range(1,5) = '[2,4]'::int4range」がtrueでないとおかしいのではと思ったのです。

int4range(1,5)はメソッドである

閉じた境界、開いた境界に引っ張られすぎて大きな勘違いをしていましたが、int4range(1,5)はメソッドでした。そのため()には特に意味はありませんでした。

またPostgreSQLの文書では「引数が2つの形式では、(閉じた下限値, 開いた上限値)という標準的な形式の範囲を生成します。引数が3つの形式では、3番目の引数で指定した形式の境界の範囲を生成します。 3番目の引数が省略されると、'[)'を指定したのと同じになる(一部省略)」とかかれています。

つまり「int4range(1,5)」は「int4range(1,5, '[)')」と境界が指定されていることになります。

int4range(1,5) = '[1,4]'::int4range が true の理由の答え

「int4range(1,5)」は「int4range(1,5, '[)')」だったからということになります。select文にすると以下のようになります。

SELECT int4range(1,5, '[)') = '[1,4]'::int4range -- true

(はじめからこう書いてくれればよかったのに。)

メソッドで境界を指定するには?

メソッドで境界を指定するには以下の2つの方法があるようです。

int4range(1,5, '[)') -- 第3引数で指定
int4range('(1,5)') -- ' ' 内で指定

引数で指定する方が一般的なようです。

おわり

きちんとPostgreSQLの文書も読んだのに、なぜtrueなのか理由にまったく気づけなかった。思い込みって怖いですね。調べたおかげで苦手だった境界に少し強くなれました。

PostgreSQL, SQL

Posted by Nakamoto