Советы по базам данных
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.jssqlite3.wasm
Плюс другие файлы:
sqlite3-opfs-async-proxy.jssqlite3-worker1.jssqlite3-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определяет формат данных, возвращаемых и передаваемых функцииcallbackcallback: функция, которая вызывается для каждой строки, возвращаемой запросом 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 .
Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.