位置情報系RubiestがMySQLを5.7から8.0にした話

静岡市でWeb開発しているkazuomatzです。

以前、[こちらの記事](https://qiita.com/kazuomatz/items/884c7b5e64a3b7532204)で、Rails + MySQL で位置情報を扱う時に標準だったライブラリ [activerecord-mysql2spatial-adapter](https://github.com/rgeo/activerecord-mysql2spatial-adapter)について書きました。

ライブラリの開発が止まってしまい、新しいRailsのバージョンに更新しようとすると対応されていないので、リポジトリをforkして、Rails6.0で何とか動かした話です。

今年、AWSの[RDSのMySQL5.7系のサポートの終了](https://blog.serverworks.co.jp/eos-rds-for-mysql57x)がアナウンスされました。2024年2月以降、RDSでMySQL5.7を利用し続けるには、有償の延長サポートに入る必要があります。

というわけで今年は、MySQL5.7で稼働しているシステムをMySQL8に更新するお仕事が数件ありました（2023年12月現在、まだまだ絶賛実施中です）。

当然、MySQL5.7とMySQL8.0に移行するにあたり非互換な部分を洗い出して行くのですが、[activerecord-mysql2spatial-adapter](https://github.com/rgeo/activerecord-mysql2spatial-adapter)にも非互換がありました。

Rails5.1以前であれば、activerecord-mysql2spatial-adapterは動作させることが可能でしたが、当時から稼働しているシステムをそのままデータベースをMySQL8アップグレードしてしまうと動かないので注意が必要です。

```
Mysql2::Error: FUNCTION some_scheme.GeomFromWKB does not exist.
````

具体的には、[MySQLのリファレンス](https://dev.mysql.com/doc/refman/8.0/ja/mysql-nutshell.html)にあるのですが、

> MySQL 5.7 では、複数の名前で使用可能ないくつかの空間関数は、空間関数ネームスペースの一貫性を高めるために非推奨になりました。各空間関数名が ST_(正確な操作を実行する場合) または MBR(最小境界矩形に基づいて操作を実行する場合) で始まるという目標です。 MySQL 8.0 では、非推奨となった関数は削除され、対応する ST_および MBR 関数のみが残されます:

> これらの関数は、ST_名を優先して削除されます: Area(), AsBinary(), AsText(), AsWKB(), AsWKT(), Buffer(), Centroid(), ConvexHull(), Crosses(), Dimension(), Distance(), EndPoint(), Envelope(), ExteriorRing(), GeomCollFromText(), GeomCollFromWKB(), GeomFromText(), GeomFromWKB(), GeometryCollectionFromText(), GeometryCollectionFromWKB(), GeometryFromText(), GeometryFromWKB(), GeometryN(), GeometryType(), InteriorRingN(), IsClosed(), IsEmpty(), IsSimple(), LineFromText(), LineFromWKB(), LineStringFromText(), LineStringFromWKB(), MLineFromText(), MLineFromWKB(), MPointFromText(), MPointFromWKB(), MPolyFromText(), MPolyFromWKB(), MultiLineStringFromText(), MultiLineStringFromWKB(), MultiPointFromText(), MultiPointFromWKB(), MultiPolygonFromText(), MultiPolygonFromWKB(), NumGeometries(), NumInteriorRings(), NumPoints(), PointFromText(), PointFromWKB(), PointN(), PolyFromText(), PolyFromWKB(), PolygonFromText(), PolygonFromWKB(), SRID(), StartPoint(), Touches(), X(), Y()。
> GLength() は、ST_Length() を優先して削除されます。

要はST_XXX という関数がMySQL5.7では非推奨ながら残っていたけど、MySQL8ではなくしたよということです。

activerecord-mysql2spatial-adapter では、
- GeomFromText
- GeometryFromWKB
- GLength

が使われています。
これらを、以下の関数を呼び出すよう置き換えなければなりません。

- ST_GeomFromText
- ST_GeometryFromWKB
- ST_Length

あー、これ、[Rails6.0対応の時にやっていた](https://qiita.com/kazuomatz/items/884c7b5e64a3b7532204)んだった。モンキーパッチ当ててもよいですが、せっかくforkしたリポジトリがあるので、各Railsのバージョンに対応しました。


## Rails4.2 の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'kazuomatz/activerecord-mysql2spatial-adapter', tag: 'v0.4.2'
```

* bundlerが1系の場合は、RubyGemsがgit:// で接続できなくなったので以下のように必要があるかもです。

```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', git: 'https://github.com/kazuomatz/activerecord-mysql2spatial-adapter', tag: 'v0.4.2'
```

## Rails5.0の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'kazuomatz/activerecord-mysql2spatial-adapter', tag: 'v0.5.0'
```

## Rails5.1の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'kazuomatz/activerecord-mysql2spatial-adapter', tag: 'v0.5.1'
```

## Rails6.0の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'kazuomatz/activerecord-mysql2spatial-adapter', tag: 'v0.6.1'
```

Rails6.1以降は・・・対応していません。過去プロジェクトで対応が必要な場合は参考になればと思います。

現在はRails7で開発するプロジェクトがあるわけですが、さすがにactiverecord-mysql2spatial-adapterを引き続き使うのは辛いので、クックパッドさんが開発している[armg](https://github.com/cookpad/armg)を使っています。