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

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

必要な経歴

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

データベースの移行

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

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

この移行ガイドでは、アプリに関連するデータを保持する 1 つ(または複数)の既存の Web SQL データベースがあることを想定しています。以下のスクリーンショットでは、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 Private File System を基盤とするブラウザでの 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 つのファイルがあります。1 つは実際のデータベース用、もう 1 つはジャーナリング情報用です。これら 2 つのファイルは、配信元のプライベート ファイル システムに存在するため、OPFS Explorer 拡張機能を使用して表示する必要があります。

OPFS Explorer の Chrome DevTools を使用して、配信元の非公開ファイル システムを検査します。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 * 雨風から星の数 10」が実行されています。その結果、Web SQL からの最初のサンプルデータの 3 行が生成されています。

Web SQL ストレージの解放

Web SQL データベースを削除できないのは(意外かもしれませんが)不可能ですが、それでも、データを SQLite Wasm に移行したら、古くなった Web SQL テーブルを削除してストレージを解放する必要があります。JavaScript を使用して Web SQL データベース内のすべてのテーブルを一覧表示してドロップするには、次のスニペットに示すコードを使用します。

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 への移行は、アプリケーションの長期的な安定性とスケーラビリティを確保したいウェブ デベロッパーにとって必要なステップです。このプロセスには初期の労力が必要になる場合がありますが、堅牢で柔軟性があり、何よりも将来性のあるデータベース ソリューションのメリットは、投資に値します。