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

SQLite Wasm はオリジンのプライベート ファイル システムを基盤としており、非推奨の Web SQL データベース テクノロジーに代わる汎用的な方法です。この記事では、Web SQL から SQLite Wasm にデータを移行する方法について説明します。

必要な経歴

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

データベースの移行

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

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

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

Chrome の DevTools で検査された Web SQL データベース。このデータベースの名前は mydatabase で、行 ID、気分、重大度という 3 つの列を持つテーブルをホストしています。サンプルデータは 3 行あります。

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

ユーザーに透過的な方法でデータを移行するには、つまり、ユーザーが移行ステップを自分で実行する必要がないようにするには、データベース内のデータを、最初に作成した元の SQL ステートメントに戻す必要があります。この課題は以前にも発生しています。この記事で使用している移行スクリプト(mywebsqldump.js)は、websqldump.js というコミュニティ ライブラリに基づいており、若干の調整が加えられています。次のコードサンプルは、ウェブ 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 プライベート ファイル システムを基盤とするブラウザの SQLite Wasm の記事をご覧ください。概要は以下のとおりです。このコードは、ライブラリによって自動的に作成される Worker で、必要な HTTP ヘッダーを正しく設定して実行する必要があります。@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 つのファイルが作成されました。これらの 2 つのファイルは送信元の非公開ファイル システムに存在するため、OPFS Explorer 拡張機能を使用して表示する必要があります。

OPFS Explorer Chrome デベロッパー ツールでオリジンの非公開ファイル システムを検査する。mydatabase.db と mydatabase.db-journal という 2 つのファイルがあります。

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

Sqlime SQLite Playground ツールで mydatabase.db ファイルを探索しています。アプリには、SQL クエリ select star from rainstorms 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 への移行は必要なステップです。このプロセスには初期段階で多少の労力が必要になる可能性がありますが、より堅牢で柔軟性があり、何よりも将来を見据えたデータベース ソリューションのメリットを考えると、投資に見合う価値があります。