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 行あります。

ウェブ 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 にインポートする

残す作業は、これらの SQL コマンドを SQLite Wasm のコンテキストで実行することだけです。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);
  }
})();

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

OPFS Explorer Chrome デベロッパー ツールでオリジンの非公開ファイル システムを検査する。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 データベース ファイルを開き、データベースに対してクエリを実行できます。以下のスクリーンショットのように、rainstorm テーブルが 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)。

まとめ

ユーザーに透過的な方法で、Web SQL データベースを、オリジンのプライベート ファイル システムを基盤とする SQLite Wasm に移行できます。データが SQLite データベースの元の非公開ファイル システムにホストされ、Web SQL に存在しなくなったことに気付くことはありません。全体として、アプリケーションの長期的な安定性とスケーラビリティを確保したいウェブ デベロッパーにとって、Web SQL から SQLite への移行は必要なステップです。このプロセスには初期段階で多少の労力が必要になる可能性がありますが、より堅牢で柔軟性があり、何よりも将来を見据えたデータベース ソリューションのメリットを考えると、投資に見合う価値があります。