Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

SQLite on Railsシリーズ(14)SQLite拡張機能をsqlpkgでインストールする(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

参考: Rails 8はSQLiteで大幅に強化された「個人が扱えるフレームワーク」(翻訳)|YassLab 株式会社

日本語タイトルは内容に即したものにしました。

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をリリースしました。

fractaledmind/sqlpkg-ruby - GitHub

これで、sqlpkgパッケージマネージャーCLIをアプリケーションにインストール可能になりました。次に必要なステップは、sqlpkg経由でインストールした SQLite拡張機能も同様にインストールされてアプリケーションに埋め込まれ、アプリのSQLiteデータベースで適切に読み込まれるようにすることだけです。

そこで、sqlpkg-ruby gemにrails generate sqlpkg:installジェネレーターを公開するRailtieを追加しました。インストーラは、以下の3つの処理を行います。

  1. 空の.sqlpkg/ディレクトリを作成します。これにより、sqlpkgが「グローバルスコープ」ではなく「プロジェクトスコープ」で実行されるようになります(詳しくはsqlpkg-cliのREADMEを参照)。

  2. 空のsqlpkg.lockファイルを作成します。このファイルは、sqlpkgがインストール済みパッケージに関する情報を保存するのに使われます(詳しくは、sqlpkg-cliのREADMEを参照)。

  3. 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リポジトリまでお気軽にお寄せください。

関連記事

SQLite on Railsシリーズ(01)Gitブランチごとにデータベースを切り替える(翻訳)

SQLite on Railsシリーズ(13)プレフィックス付きのULIDキー(翻訳)


  1. 原注: SQLite拡張機能のインストールに関する一般的な概要についてはこちらの記事を参照してください。 

CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。