Từ Web SQL sang SQLite Wasm: hướng dẫn di chuyển cơ sở dữ liệu

Với SQLite Wasm được hỗ trợ bởi hệ thống tệp riêng gốc, bạn có thể thay thế linh hoạt công nghệ cơ sở dữ liệu Web SQL không còn được dùng nữa. Bài viết này là hướng dẫn di chuyển dữ liệu từ Web SQL sang SQLite Wasm.

Nền bắt buộc

Bài đăng Ngừng sử dụng và xoá Web SQL đã thông báo về việc ngừng sử dụng công nghệ cơ sở dữ liệu Web SQL. Mặc dù bản thân công nghệ này có thể không còn được dùng nữa, nhưng các trường hợp sử dụng mà công nghệ này giải quyết thì vẫn còn rất nhiều. Vì vậy, bài đăng tiếp theo SQLite Wasm trong trình duyệt được hỗ trợ bởi Hệ thống tệp riêng tư gốc sẽ trình bày một bộ công nghệ thay thế dựa trên cơ sở dữ liệu SQLite, được biên dịch thành Web Assembly (Wasm) và được hỗ trợ bởi hệ thống tệp riêng tư gốc. Để kết thúc bài viết này, chúng tôi sẽ hướng dẫn cách di chuyển cơ sở dữ liệu từ Web SQL sang SQLite Wasm.

Di chuyển cơ sở dữ liệu

Bốn bước sau đây minh hoạ ý tưởng khái niệm về việc di chuyển cơ sở dữ liệu Web SQL sang SQLite Wasm, trong đó cơ sở dữ liệu SQLite được hỗ trợ bởi hệ thống tệp riêng của nguồn gốc. Đây có thể là nền tảng cho mã của riêng bạn được tuỳ chỉnh theo nhu cầu di chuyển SQL trên web.

(Các) cơ sở dữ liệu Web SQL cần di chuyển

Giả định cơ sở của hướng dẫn di chuyển này là bạn có một (hoặc một số) cơ sở dữ liệu Web SQL hiện có chứa dữ liệu liên quan đến ứng dụng của bạn. Trong ảnh chụp màn hình bên dưới, bạn sẽ thấy một cơ sở dữ liệu mẫu có tên mydatabase với bảng mưa bão liên kết tâm trạng với mức độ nghiêm trọng. Công cụ của Chrome cho nhà phát triển cho phép bạn xem cơ sở dữ liệu Web SQL để gỡ lỗi, như trong ảnh chụp màn hình sau.

Cơ sở dữ liệu SQL Web được kiểm tra trong DevTools của Chrome. Cơ sở dữ liệu có tên là mydatabase và lưu trữ một bảng có 3 cột: mã nhận dạng hàng, tâm trạng và mức độ nghiêm trọng. Có 3 hàng dữ liệu mẫu.

Dịch cơ sở dữ liệu Web SQL sang câu lệnh SQL

Để di chuyển dữ liệu theo cách minh bạch với người dùng, tức là không yêu cầu họ tự thực hiện bất kỳ bước di chuyển nào, các phần dữ liệu trong cơ sở dữ liệu cần được dịch trở lại các câu lệnh SQL ban đầu đã tạo ra các phần dữ liệu đó. Thách thức này đã từng xuất hiện và tập lệnh di chuyển được sử dụng trong bài viết này – mywebsqldump.js – dựa trên một thư viện cộng đồng có tên là websqldump.js, với một số điều chỉnh nhỏ. Mã mẫu sau đây cho thấy mã cần thiết để dịch cơ sở dữ liệu SQL Web mydatabase thành một tập hợp câu lệnh SQL.

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

Khi chạy mã này, bạn sẽ thấy chuỗi câu lệnh SQL bên dưới.

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');

Nhập dữ liệu vào SQLite Wasm

Tất cả việc còn lại là thực thi các lệnh SQL này trong ngữ cảnh của SQLite Wasm. Để biết tất cả thông tin chi tiết về cách thiết lập SQLite Wasm, bạn có thể tham khảo bài viết SQLite Wasm trong trình duyệt được Hệ thống tệp riêng của Origin hỗ trợ, nhưng nội dung tóm tắt lại được trình bày bên dưới. Hãy nhớ rằng mã này cần chạy trong một Worker (mà thư viện sẽ tự động tạo cho bạn), với các tiêu đề HTTP bắt buộc được đặt chính xác. Bạn có thể cài đặt gói @sqlite.org/sqlite-wasm từ 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);
  }
})();

Sau khi chạy mã này, hãy kiểm tra tệp cơ sở dữ liệu đã nhập bằng tiện ích OPFS Explorer (Trình khám phá OPFS) của Công cụ của Chrome cho nhà phát triển. Hiện có hai tệp, một tệp chứa cơ sở dữ liệu thực tế và một tệp chứa thông tin nhật ký. Xin lưu ý rằng hai tệp này nằm trong hệ thống tệp riêng tư gốc, vì vậy, bạn cần sử dụng tiện ích Trình khám phá OPFS để xem các tệp đó.

Kiểm tra hệ thống tệp riêng tư gốc bằng Công cụ của Chrome cho nhà phát triển OPFS Explorer. Có hai tệp, một tệp có tên mydatabase.db và một tệp có tên mydatabase.db-journal.

Để thực sự xác minh rằng dữ liệu đã nhập giống với dữ liệu Web SQL ban đầu, hãy nhấp vào tệp mydatabase.db và tiện ích Trình khám phá OPFS sẽ hiển thị hộp thoại Save File (Lưu tệp) để cho phép bạn lưu tệp trong hệ thống tệp mà người dùng nhìn thấy. Khi tệp cơ sở dữ liệu đã được lưu, hãy sử dụng ứng dụng trình xem SQLite để khám phá dữ liệu. Project Fugu API Showcase (Bản minh hoạ API của Dự án Fugu) có một số ứng dụng để làm việc với SQLite trong trình duyệt. Ví dụ: Sqlime — SQLite Playground cho phép bạn mở tệp cơ sở dữ liệu SQLite từ ổ đĩa cứng và chạy truy vấn trên cơ sở dữ liệu. Như bạn thấy trong ảnh chụp màn hình bên dưới, bảng mưa lớn đã được nhập chính xác vào SQLite.

Khám phá tệp mydatabase.db trong công cụ Sqlime SQLite Playground. Ứng dụng này hiển thị với truy vấn SQL select star from rainstorms limit 10 đang chạy, dẫn đến 3 hàng từ dữ liệu mẫu ban đầu của Web SQL.

Giải phóng bộ nhớ Web SQL

Mặc dù (có thể là điều đáng ngạc nhiên) không thể xoá cơ sở dữ liệu Web SQL, nhưng bạn vẫn nên giải phóng một số bộ nhớ bằng cách xoá các bảng Web SQL hiện đã lỗi thời sau khi di chuyển dữ liệu vào SQLite Wasm. Để liệt kê tất cả các bảng trong cơ sở dữ liệu Web SQL và thả các bảng đó bằng JavaScript, hãy sử dụng mã như trong đoạn mã sau:

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);
  }
};

Làm việc với dữ liệu sau khi di chuyển

Sau khi di chuyển dữ liệu, hãy xử lý dữ liệu như được nêu trong Mã mẫu để bắt đầu. Hãy xem tài liệu tham khảo về API SQLite Wasm để biết thông tin chi tiết. Xin nhắc lại rằng bạn cần truy cập SQLite Wasm từ một Worker nếu sử dụng hệ thống tệp riêng tư gốc làm phần phụ trợ bộ nhớ.

Kiểm thử

Bản minh hoạ này cho phép bạn điền dữ liệu mẫu vào cơ sở dữ liệu Web SQL, sau đó kết xuất dữ liệu Web SQL dưới dạng câu lệnh SQL. Tiếp theo, dữ liệu này sẽ được nhập vào SQLite Wasm dựa trên hệ thống tệp riêng của nguồn gốc. Cuối cùng, bạn giải phóng bộ nhớ bằng cách xoá dữ liệu SQL web đã lỗi thời. Hãy kiểm tra mã nguồn để biết cách triển khai đầy đủ, bao gồm cả tệp mywebsqldump.js đã vá.

Ứng dụng minh hoạ tại web-sql-to-sqlite-wasm.glitch.me.

Kết luận

Bạn có thể di chuyển cơ sở dữ liệu Web SQL sang SQLite Wasm được hỗ trợ bởi hệ thống tệp riêng tư gốc theo cách minh bạch với người dùng. Người dùng sẽ không nhận thấy rằng dữ liệu của họ hiện được lưu trữ trong hệ thống tệp riêng tư gốc trong cơ sở dữ liệu SQLite và không còn nằm trong Web SQL nữa. Nhìn chung, việc di chuyển từ Web SQL sang SQLite là một bước cần thiết đối với các nhà phát triển web muốn đảm bảo tính ổn định và khả năng mở rộng lâu dài của ứng dụng. Mặc dù quá trình này có thể đòi hỏi một số nỗ lực ban đầu, nhưng lợi ích của một giải pháp cơ sở dữ liệu mạnh mẽ hơn, linh hoạt hơn và quan trọng nhất là phù hợp với tương lai sẽ khiến bạn cảm thấy đáng đầu tư.