Web SQL から SQLite Wasm へ: データベース移行ガイド

元のプライベート ファイル システムを基盤とする SQLite Wasm を使用することで、非推奨の Web SQL データベース テクノロジーの汎用性の高い代替手段があります。この記事では、Web SQL から SQLite Wasm にデータを移行する方法について説明します。

必要な学歴

Web SQL のサポート終了と削除の投稿で、Web SQL データベース テクノロジーのサポート終了を発表しました。テクノロジー自体は非推奨になる可能性がありますが、このテクノロジーで対処されるユースケースは大部分ではありません。フォローアップのオリジン プライベート ファイル システムを基盤とするブラウザにおける SQLite Wasm では、SQLite データベースをベースとウェブ アセンブリ(Wasm)にコンパイルされ、オリジン プライベート ファイル システムを基盤とする代替テクノロジー セットの概要を説明しています。この記事では、データベースを Web SQL から SQLite Wasm に移行する方法について説明します。

データベースの移行

次の 4 つのステップは、Web SQL データベースを SQLite Wasm に移行するという概念的な考え方を示しています。SQLite データベースは元のプライベート ファイル システムを基盤としています。これは、お客様の Web SQL 移行のニーズに合わせてカスタマイズした独自のコードの基盤として使用できます。

移行する Web SQL データベース

この移行ガイドでは、アプリに関連するデータが保持されている既存の Web SQL データベースが 1 つ(複数可)あることを前提としています。次のスクリーンショットは、mydatabase というサンプル データベースに、気分と重大度をマッピングするレインストーム テーブルが含まれています。Chrome DevTools を使用すると、次のスクリーンショットのように、デバッグ用の Web SQL データベースを表示できます。

Chrome の DevTools で検査された Web SQL データベース。データベースは mydatabase と呼ばれ、3 つの列(行 ID、ムード、重大度)を含むテーブルをホストします。サンプルデータは 3 行あります。

Web SQL データベースを SQL ステートメントに変換する

ユーザーに対する透過的な方法でデータを移行するには、つまりユーザーが自身で移行手順を実行する必要がないようにするには、データベース内のデータをそもそもそのデータを作成した元の SQL ステートメントに変換する必要があります。この問題は以前に発生した問題で、この記事で使われている移行スクリプト(mywebsqldump.js)は websqldump.js というコミュニティ ライブラリをベースに、多少の調整を加えたものです。次のコードサンプルは、Web SQL データベースの mydatabase を一連の SQL ステートメントに変換するために必要なコードを示しています。

websqldump.export({
  database: 'mydatabase',
  version: '1.0',
  success: function(sql) {
    // The SQL statements.
  },
  error: function(err) {
    // Handle the error.
  }
});

このコードを実行すると、以下の SQL ステートメント文字列が生成されます。

CREATE TABLE IF NOT EXISTS rainstorms (mood text, severity int);
INSERT INTO rainstorms(mood,severity) VALUES ('somber','6');
INSERT INTO rainstorms(mood,severity) VALUES ('rainy','8');
INSERT INTO rainstorms(mood,severity) VALUES ('stormy','2');

SQLite Wasm にデータをインポートする

あとは、SQLite Wasm のコンテキストでこれらの SQL コマンドを実行することだけです。SQLite Wasm の設定に関するすべての詳細については、Origin Private File System に支えられたブラウザでの SQLite Wasm の設定を参照してくださいが、要点は次のとおりです。このコードは、必要な HTTP ヘッダーを正しく設定した Worker(ライブラリが自動的に作成するもの)で実行する必要があります。@sqlite.org/sqlite-wasm パッケージは、npm からインストールできます。

import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';

(async () => {
  try {
    const promiser = await new Promise((resolve) => {
      const _promiser = sqlite3Worker1Promiser({
        onready: () => {
          resolve(_promiser);
        },
      });
    });

    let response;

    response = await promiser('open', {
      filename: 'file:mydatabase.db?vfs=opfs',
    });
    const { dbId } = response;

    const sql = `
      CREATE TABLE IF NOT EXISTS rainstorms (mood text, severity int);
      INSERT INTO rainstorms(mood,severity) VALUES ('somber','6');
      INSERT INTO rainstorms(mood,severity) VALUES ('rainy','8');
      INSERT INTO rainstorms(mood,severity) VALUES ('stormy','2');`
    await promiser('exec', { dbId, sql });

    await promiser('close', { dbId });
  } catch (err) {
    if (!(err instanceof Error)) {
      err = new Error(err.result.message);
    }
    console.error(err.name, err.message);
  }
})();

このコードを実行したら、インポートしたデータベース ファイルを Chrome DevTools 拡張機能 OPFS Explorer で調べます。現在、ファイルは 2 つあります。1 つは実際のデータベースに関するもので、もう 1 つはジャーナリング情報に関するものです。これら 2 つのファイルは元の非公開ファイル システムに存在するため、OPFS Explorer 拡張機能を使用して表示する必要があります。

OPFS Explorer の Chrome DevTools を使用して元の非公開ファイル システムを検査する。2 つのファイルがあります。1 つは mydatabase.db、もう 1 つは mydatabase.db-journal です。

インポートしたデータが最初の Web SQL データと同じであることを実際に検証するには、mydatabase.db ファイルをクリックします。OPFS Explorer 拡張機能によって [Save File] ダイアログが表示され、ユーザーに表示されるファイル システムにファイルを保存できます。データベース ファイルを保存して、SQLite ビューアアプリを使用してデータを調べます。Project Fugu API Showcase には、ブラウザで SQLite を操作するアプリがいくつか用意されています。たとえば、Sqlime - SQLite Playground を使用すると、ハードディスクから SQLite データベース ファイルを開いてデータベースに対してクエリを実行できます。以下のスクリーンショットからわかるように、レインストーム テーブルは SQLite に正しくインポートされています。

Sqlime SQLite プレイグラウンド ツールで mydatabase.db ファイルの内容を確認します。このアプリでは、SQL クエリ「selectstar from rainstars limit 10」が実行されており、Web SQL からの最初のサンプルデータから 3 行が取得されている。

Web SQL ストレージの解放

意外かもしれませんが、Web SQL データベースは削除できませんが、SQLite Wasm にデータを移行した後は、古くなった Web SQL テーブルを削除して空き容量を増やす必要があります。Web SQL データベース内のすべてのテーブルを一覧表示し、JavaScript を使用してそれらを削除するには、次のスニペットのようなコードを使用します。

const dropAllTables = () => {
  try {
    db.transaction(function (tx) {
      tx.executeSql(
        "SELECT name FROM sqlite_master WHERE type='table' AND name !='__WebKitDatabaseInfoTable__'",
        [],
        function (tx, result) {
          const len = result.rows.length;
          const tableNames = [];
          for (let i = 0; i < len; i++) {
            const tableName = result.rows.item(i).name;
            tableNames.push(`'${tableName}'`);
            db.transaction(function (tx) {
              tx.executeSql('DROP TABLE ' + tableName);
            });
          }
          console.log(`Dropped table${tableNames.length > 1 ? 's' : ''}: ${tableNames.join(', ')}.`);
        }
      );
    });
  } catch (err) {
    console.error(err.name, err.message);
  }
};

移行後のデータの操作

データを移行したら、スタートガイドのコードサンプルに沿ってデータを処理します。詳しくは、SQLite Wasm API リファレンスをご覧ください。繰り返しになりますが、元のプライベート ファイル システムをストレージ バックエンドとして使用する場合は、Worker から SQLite Wasm にアクセスする必要があります。

テストする

このデモでは、Web SQL データベースにサンプルデータを入力し、Web SQL データを SQL ステートメントとしてダンプできます。次に、元の非公開ファイル システムを基盤とする SQLite Wasm にインポートされます。最後に、古い Web SQL データを削除してストレージを解放します。パッチが適用された mywebsqldump.js ファイルを含め、完全な実装については、ソースコードをご確認ください。

web-sql-to-sqlite-wasm.glitch.me のデモアプリ

まとめ

元のプライベート ファイル システムを基盤とする SQLite Wasm に、Web SQL データベースを移行することで、ユーザーが意識することはありません。データが SQLite データベースの元のプライベート ファイル システムにホストされ、Web SQL に存在しなくなったことに気づくことはありません。総じて、アプリケーションの長期的な安定性とスケーラビリティを確保したいと考えているウェブ デベロッパーにとって、Web SQL から SQLite への移行は必要なステップです。このプロセスには初期の労力が必要になるかもしれませんが、より堅牢で柔軟性が高く、そして何よりも将来性のあるデータベース ソリューションの利点があるため、投資する価値があります。