Советы по базам данных

SQLite 3 в действии: руководство для начинающих по использованию реляционной базы данных в браузере

SQLite 3 и WebAssembly: как использовать легкую, бесплатную базу данных с открытым исходным кодом в вашем браузере

Несколько месяцев назад была выпущена версия SQLite 3, скомпилированная для WebAssembly. Что это значит? Это означает возможность использовать SQLite 3 изначально в браузере. Другими словами, в нашем распоряжении мощь и простота использования одной из лучших реляционных баз данных прямо из браузера. Я начал экспериментировать с этой возможностью и создал страницу для проверки основных операций. В этом посте я сообщу свои заметки об основных шагах, которым нужно следовать.

SQLite 3

Но сначала, что такое SQLite 3? SQlite — это реляционная база данных, сохраненная в файле, легкая и бесплатная. В отличие от других баз данных, SQLite не требует никаких серверов. В этом отношении он очень напоминает MS Access. Вот две характеристики, которые побуждают меня углублять эту технологию:

  • Это бесплатно
  • это с открытым исходным кодом
  • можно работать локально

Это позволяет создавать приложения, которые могут работать полностью в автономном режиме.

Вы можете найти всю документацию, информацию и загрузки по SQLite 3 на официальном сайте: sqlite.org.

Веб-сборка

В чем проблема? Что до сих пор было невозможно использовать SQLite непосредственно на веб-странице. Вернее, это было возможно, но только через какие-то независимые проекты. Для решения этой проблемы (и, подозреваю, еще и для учета некоторых запросов от Google) была создана версия SQLite 3, скомпилированная для WebAssembly.

Опять же, вы можете найти всю документацию и информацию на официальном сайте.

Как использовать SQLite 3 в браузере

Сказав это, давайте перейдем к самой интересной части: как мы можем использовать SQLite 3 в браузере?

Для начала нам нужно скачать некоторые файлы с сайта. Ищем файл sqlite-wasm-XXXX.zip (где XXXX — версия SQLite 3, которую мы хотим использовать) и скачиваем его. Внутри находим папку jswasm с нужными нам файлами:

  • sqlite3.js
  • sqlite3.wasm

Плюс другие файлы:

  • sqlite3-opfs-async-proxy.js
  • sqlite3-worker1.js
  • sqlite3-worker1-promiser.js

Мы можем создать папку в проекте и добавить ссылку на эти файлы:

<head>
  <!-- ... -->
  <script src="jswasm/sqlite3.js"></script>
  <!-- ... -->
</head>

Вам нужно импортировать только один раз sqlite3.js, чтобы загрузить sqlite3.wasm. Но прежде чем мы сможем использовать SQLite 3, нам нужно инициализировать библиотеку. Давайте создадим функцию, которая может нам помочь:

const initSqlite3 = async () => {
  const sqlite3 = await self["sqlite3InitModule"]();
  self["sqlite3"] = sqlite3;
  return sqlite3;
};

Таким образом, мы можем получить доступ к SQLite 3 через self["sqlite3"] из любого места в коде.

Мы можем убедиться, что все работает правильно:

initSqlite3().then((s) => {
  sqlite3 = s;
  console.log("sqlite3:", sqlite3);
  console.log("sqlite3", self["sqlite3"]);
  console.log("sqlite3 version", sqlite3.capi.sqlite3_libversion());
});

Как создать базу данных с помощью SQLite 3

Теперь, когда мы инициализировали SQLite 3, мы можем создать базу данных. Сначала давайте создадим функцию, которая поможет нам:

export const createDatabase = (filename = ":memory:", flags = "c") =>
  new self["sqlite3"].oo1.DB({ filename, flags });

В этом случае мы используем конструктор oo1.DB. Стоит упомянуть значение флагов:

  • c: создайте, если он не существует, иначе сбой, если он не существует. Подразумевает флаг w.
  • w: пиши. Подразумевает r: база данных не может быть доступна только для записи.
  • r: доступен только для чтения, если не указаны ни w, ни c, иначе игнорируется.
  • t: включить отслеживание SQL, выполняемого на этом дескрипторе базы данных, отправляя его на console.log().

Еще одного упоминания заслуживает параметр filename. Есть зарезервированные слова:

  • :memory:: создать базу данных в памяти
  • "": создать временную базу данных
  • :localStorage:: создать базу данных в локальном хранилище браузера
  • :sessionStorage:: создать базу данных в хранилище сеансов браузера

Тем не менее, для создания базы данных вам просто нужно:

const db = createDatabase("xyz.sqlite3", "ct");
console.log("db", db.filename); // xyz.sqlite3

Как добавить таблицу в базу данных SQLite 3

Пустая база данных не очень полезна. Итак, приступим к созданию таблицы методом exec:

const createTable = (db, tableName) =>
  db.exec({
    sql: `CREATE TABLE IF NOT EXISTS "${tableName}"(a,b)`,
  });

Мы можем использовать метод exec для одновременного выполнения нескольких операций:

db.exec(["create table t(a);", "insert into t(a) ", "values(10),(20),(30)"]);

Как вставить данные в таблицу

Конечно, мы должны ввести значения в таблицу. Также в этом случае мы можем использовать метод exec:

const insertData = (db, tableName, data) =>
  db.exec({
    sql: `INSERT INTO "${tableName}" VALUES(?,?)`,
    bind: data,
  });

Мы используем функцию для генерации случайных чисел:

const rand = (max) => Math.floor(Math.random() * max);

И давайте создадим цикл для вставки некоторых значений:

const addFakeData = (tableName) => {
  let i = 0;
  for (i = 20; i <= 25; ++i) {
    insertData(db, tableName, [rand(100), rand(100)]);
  }
};

Существуют различные способы добавления данных в таблицу. Можем попробовать и другие варианты:

const addFakeData = (tableName) => {
  let i = 0;
  for (i = 20; i <= 25; ++i) {
    insertData(db, tableName, [rand(100), rand(100)]);
    db.exec({
      sql: `insert into "${tableName}"(a,b) values (?,?)`,
      bind: [rand(100), rand(100)],
    });
    db.exec({
      sql: `insert into "${tableName}"(a,b) values ($a,$b)`,
      bind: { $a: rand(100), $b: rand(100) },
    });
  }
};

Чтение данных из базы данных SQLite 3

Следующий шаг — понять, как читать данные, содержащиеся в таблице. Снова используем метод exec. Добавим два варианта:

  • rowMode: array или object определяет формат данных, возвращаемых и передаваемых функции callback
  • callback: функция, которая вызывается для каждой строки, возвращаемой запросом sql.
const readData = (db, tableName, callback) =>
  db.exec({
    sql: `SELECT * FROM "${tableName}"`,
    rowMode: "array",
    callback,
  });

То есть в нашем случае:

const getFakeData = (db, tableName) => {
  let result = [];
  db.exec({
    sql: `select a as aa, b as bb from "${tableName}" order by aa limit 10`,
    rowMode: "object",
    callback: function (row) {
      console.log("row ", ++this.counter, "=", JSON.stringify(row));
      result = [...result, row];
    }.bind({ counter: 0 }),
  });
  return result;
};

Мы также можем упростить код, установив returnValue равным resultRows:

const getFakeData = (db, tableName) =>
  db.exec({
    sql: `select a as aa, b as bb from "${tableName}" order by aa limit 10`,
    rowMode: "object",
    returnValue: "resultRows",
  });

Как сохранить базу данных SQLite 3 в файл

Наконец, последняя проблема, которую нам нужно решить, — это выяснить, как сохранить базу данных SQLite на вашем компьютере. Для этого нам нужно использовать C-style API и метод sqlite3_js_db_export().

const byteArray = self["sqlite3"].capi.sqlite3_js_db_export(db.pointer);

Метод sqlite3_js_db_export() возвращает Uint8Array. Мы можем использовать его, чтобы получить Blob:

const blob = new Blob([byteArray.buffer], {
  type: "application/x-sqlite3",
});

Чтобы упростить код, мы можем использовать функцию:

const downloadDB = (db) => {
  const byteArray = self["sqlite3"].capi.sqlite3_js_db_export(db.pointer);
  const blob = new Blob([byteArray.buffer], {
    type: "application/x-sqlite3",
  });
  const a = document.createElement("a");
  document.body.appendChild(a);
  a.href = window.URL.createObjectURL(blob);
  a.download = db.filename.split("/").pop() || db.name;
  a.addEventListener("click", function () {
    setTimeout(function () {
      console.log("Exported (possibly auto-downloaded) database");
      window.URL.revokeObjectURL(a.href);
      a.remove();
    }, 500);
  });
  a.click();
};

Спасибо за прочтение! Оставайтесь с нами, чтобы узнать больше.

Не пропустите мою следующую статью — подпишитесь на мой средний список адресов электронной почты



Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.