親愛なるジョンからの手紙

雑記です。ゲームとか漫画とかプログラミングとか。

H2GISでPostGISの代理やろうとして面倒だなコレって知見を得た話

概要

ここ数日お仕事でH2DBを使って動的クエリのテストをしようとアホほど頭を悩ませていたのですが、単にデータベース使うだけでなく地理計算系の拡張を突っ込んでいる部分もまとめてテストしようとしたせいでまあ面倒なこと面倒なこと。舐めてかかると地獄なことになるという知見を得ました。

なので本日は何がクソ面倒なのかをまとめていこうと思います。ググればわかるっちゃわかるけど日本語の記事がほとんどなかったのでまとめの一つとして記述。

登場人物

H2DB

H2 Database Engine

コードに組み込みで動くRDB。オンメモリで動かして各種DBMSの方言用ドライバも完備。JVM上で動く。MPL

H2GIS

H2GIS • Spatial H2

H2DBに地理計算系とか幾何計算とかの関数やら型やらを突っ込む拡張。LGPL3.0

PostgreSQL

PostgreSQL: The world's most advanced open source database

説明いる?RDB。知らないならこんなクソブログ読んでないでRDBについて調べなおせ。

PostGIS

PostGIS — Spatial and Geographic Objects for PostgreSQL

PostgreSQLに地理計算系とか幾何計算とかの関数やら型やらを突っ込む拡張。GPL2.0

やろうとしたこと

PostgreSQLに投げる動的クエリ作ってるところがパラメータによってちゃんとSQL通るかどうかを確認したかった

せや!H2GIS使ったろ!地理計算ならだいたい変わらんやろ!(安直)

テストコード走らせてるときはH2DBを利用。そうでないときは接続文字列に従い正しいデータベースにつなぐ。環境変数で切り替えられるだろ多分。

この安直さ極まる思考により後に死ぬことになる。

知見

そもそもH2GISとPostGISで地理計算系の仕様が微妙に違う

H2GIS、PostGISOGCで定義されている「Simple Feature SQL」と呼ばれる、SQLで地理情報を扱うための仕様に準拠しています。

http://www.opengeospatial.org/standards/sfs

ただし、H2GISはほぼ完全に仕様準拠な一方、PostGISは「Simple Feature SQLの拡張仕様」となっており、PostGISで利用可能なもろもろがH2GISで利用できないということが多々あります。

例として挙げると、地理情報の基本的な方となるGEOMETRY型にすら大きな違いがあります。Simple Feature SQLは地理情報のSRID(地理情報の空間参照方法のIDみたいなもの。本筋からは逸れるので詳しくはググれ)が型の情報として埋め込めなかったり、テーブル定義の際にWKT(Well Known Text 詳しくはググれ)形式のような地理情報地理情報の形状を制約として設定できなかったりします。

テスト用のテーブル作ってるときに、この辺の差異のせいでdumpを使ってデータベース構築できずに必死こいて手書きしました。

同じ名前の関数でも引数や結果が異なる関数がある

例としてはST_Areaと呼ばれる、GEOMETRY型を引数にとってその面積を出力する関数が存在します。

PostGISではGEOMETRY型がSRIDを持つため、地理参照系や地球が球状であるということを考慮した計算や、どの空間参照系を利用して面積を出力するかの設定を行うことができるのですが、H2GISでは座標を2次元平面として見立てた幾何学計算のみを行います。

ST_Area

https://postgis.net/docs/ST_Area.html

GEOGRAPHY型が存在しない

GEOGRAPHY型はGEOMETRYよりも計算に特化した地理情報の型なのですが、これがH2GISには存在していません。そのため、SQL内でGEOGRAPHY型を利用しているとH2GISでは例外が投げられます。

ジオグラフィ型というものがある - Qiita

なぜ面倒なことになったのか

上記のことを全部やらかしてしまっていたため。もっとよく調べてから手を出すべきでした。くそう。

知見からの対策

もし僕のような利用目的でH2GISを利用したい場合、選択肢は二択です。

  • H2GISを利用しない。Docker HubとかVagrant CloudとかにPostGISやらマスタデータやら設定済みのイメージを置いて共有する。
  • H2GISを利用する。気合で実際に実行した内容と結果見ながらSQLで調整する。プロダクトコードが通るかつ実値が近いものになるようにする。無理なものは実値を検証しない。

推奨は上です。僕は下でやって世界を呪いました。 もしH2GISとPostGISを併用するケースがあるなら、安易に採択しないことをお勧めします。ていうかそもそもそんなテストする必要がある動的SQL作らないことをお勧めします。

まとめ

もうH2GISなんてコリゴリだよ~~!!(ワイプ)