SQLite on Railsシリーズ(14)SQLite拡張機能をsqlpkgでインストールする(翻訳)
前回の記事では、Ruby gemとして配布されているSQLite拡張機能をRuby on Railsアプリケーションで読み込む方法について説明しました。残念ながら、Ruby gemとして配布されているSQLite拡張機能は多くありません。そこで本記事では、より幅広いSQLite拡張機能をアプリにインストールする方法を詳しく解説します。
SQLiteは、SQL標準に関する機能は基本的に完全ですが、SQLiteでサポートしていない特定のデータベース関連ニーズが生じる場合もあります。
ありがたいことに、SQLiteは豊富な拡張機能エコシステムを提供しています。さらに幸運なことに、sqlpkg
というパッケージマネージャ(非公式)と、それに対応するパッケージレジストリ(非公式)もあります。
現在、同レジストリでは62個(訳注: 現在は103個)の拡張機能が利用可能です。では、これらの拡張機能をRailsアプリにインストールして読み込むにはどうすればよいでしょうか?1
sqlpkg
パッケージマネージャは、実行中のOSに適した実行可能ファイルをインストールしてくれます。面倒なのは、OSに適したsqlpkg
実行可能ファイル自体をインストールすることでした。
ちょうど他のプロジェクトでwebiインストーラを使っていたので、sqlpkg
用のwebiインストーラを追加してみることにしました。他のwebiインストーラーのソースをいくつか読んだ後、sqlpkg
用の実用的なインストーラをまとめました(#651)。
これでsqlpkg
実行可能ファイルをホストマシンに手軽にインストールできるようになりましたが、拡張機能をアプリにインストールするための手動の手順もさらに必要でした。私の目標は常に、アプリの設定をできるだけアプリ自体に埋め込むことなので、拡張機能をアプリ自体にインストールする方法を見つけたいと考えていました。
この問題について何週間も悩みながら、私は他のプロジェクトに取り組み始めました。そのプロジェクトの1つは、Litestreamユーティリティ用のRubyGemsラッパーを提供することでした。私はそのプロジェクトを学習の機会として利用し、BundlerがホストマシンのOSに適した実行可能ファイルを自然な形でRuby gemにインストールする方法を調べることで、実行可能ファイルをバンドルする方法を学びました。そのプロセスとそのgemについては過去記事で詳しく書きましたが、その基本的なアプローチはまさに私がsqlpkg
実行可能ファイルに求めていたものでした。
そこで、Rails アプリにsqlpkg
実行ファイルをインストールするRuby gemを作成し、数日前にsqlpkg-ruby
gemをリリースしました。
これで、sqlpkg
パッケージマネージャーCLIをアプリケーションにインストール可能になりました。次に必要なステップは、sqlpkg
経由でインストールした SQLite拡張機能も同様にインストールされてアプリケーションに埋め込まれ、アプリのSQLiteデータベースで適切に読み込まれるようにすることだけです。
そこで、sqlpkg-ruby
gemにrails generate sqlpkg:install
ジェネレーターを公開するRailtieを追加しました。インストーラは、以下の3つの処理を行います。
- 空の
.sqlpkg/
ディレクトリを作成します。これにより、sqlpkg
が「グローバルスコープ」ではなく「プロジェクトスコープ」で実行されるようになります(詳しくはsqlpkg-cli
のREADMEを参照)。 -
空の
sqlpkg.lock
ファイルを作成します。このファイルは、sqlpkg
がインストール済みパッケージに関する情報を保存するのに使われます(詳しくは、sqlpkg-cli
のREADMEを参照)。 -
config/initializers/sqlpkg.rb
イニシャライザファイルを作成します。このファイルは、データベースが開かれるたびに.sqlpkg/
ディレクトリにインストールされている拡張機能を自動的に読み込むためのパッチをSQLite3Adapter
に適用します。
以上すべてがうまく動くための鍵となるのが、以下のイニシャライザファイルです。
module SqlpkgLoader
def configure_connection
super
@raw_connection.enable_load_extension(true)
Dir.glob(".sqlpkg/**/*.{dll,so,dylib}") do |extension_path|
@raw_connection.load_extension(extension_path)
end
@raw_connection.enable_load_extension(false)
end
end
ActiveSupport.on_load(:active_record_sqlite3adapter) do
prepend SqlpkgLoader
end
これら3つのステップを組み合わせることで、SQLite拡張機能をRailsアプリケーションにインストールできるようになります。Railsアプリケーションに適切に統合したら、以下のコマンドを実行するとsqlpkg
レジストリにリストされている拡張機能をインストールできます。
$ bundle exec sqlpkg install PACKAGE_IDENTIFIER
sqlpkg
レジストリに登録されている拡張機能を調べる場合、カードにタイトルとして表示されているPACKAGE_IDENTIFIER
は拡張機能をインストールするときに指定する必要があり、常に所有者/名前
の形式を取ります。たとえば、ベクトル類似性検索をサポートするsqlite-vss
拡張機能をインストールするには、sqlpkg.orgサイトで以下のasg017/vss
というパッケージカードを見つけます。
次に以下を実行してRailsアプリに拡張機能をインストールします。
$ bundle exec sqlpkg install asg017/vss
ターミナルには以下のような結果が表示されます。
(project scope)
> installing asg017/vss...
✓ installed package asg017/vss to .sqlpkg/asg017/vss
.sqlpkg/
ディレクトリ内に新しいファイルが追加され、sqlpkg.lock
ファイルにも新しいエントリが追加されます。
{
"packages": {
"asg017/vss": {
"owner": "asg017",
"name": "vss",
"version": "v0.1.2",
"specfile": "https://github.com/nalgeon/sqlpkg/raw/main/pkg/asg017/vss.json",
"assets": {} -- # (以下省略)
}
}
}
これで完了です。Railsアプリでsqlite-vss
拡張機能を利用可能になりました。sqlpkg
レジストリで利用可能な62個のSQLite拡張機能のいずれかでも同じことができます。ダウンロードした拡張機能は、アプリを起動したときに自動的にアプリのSQLiteデータベースに読み込まれて利用可能になります。
私は、これはSQLite on Railsにとってさらなる大きな前進だと思います。お役に立てば幸いです。ご質問やご意見はTwitterまたはGitHubリポジトリまでお気軽にお寄せください。
概要
原著者の許諾を得て翻訳・公開いたします。
参考: Rails 8はSQLiteで大幅に強化された「個人が扱えるフレームワーク」(翻訳)|YassLab 株式会社
日本語タイトルは内容に即したものにしました。