From d69169d880addb371f6ea8f4ed24ce453701766d Mon Sep 17 00:00:00 2001 From: Roy Hashimoto Date: Tue, 31 Oct 2023 15:30:33 -0700 Subject: [PATCH] Add file import verifier. --- demo/file/index.html | 5 +---- demo/file/index.js | 26 +++++++++++++++++++++++--- demo/file/verifier.js | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 demo/file/verifier.js diff --git a/demo/file/index.html b/demo/file/index.html index b590e31d..817a8ad6 100644 --- a/demo/file/index.html +++ b/demo/file/index.html @@ -4,18 +4,15 @@ Local file transfer +

Sample database importer

-
- -

\ No newline at end of file diff --git a/demo/file/index.js b/demo/file/index.js index 4df2c1be..779f6ebf 100644 --- a/demo/file/index.js +++ b/demo/file/index.js @@ -10,11 +10,27 @@ const DBFILE_MAGIC = 'SQLite format 3\x00'; document.getElementById('file-import').addEventListener('change', async event => { let vfs; try { - log('Importing database...'); + log(`Importing to IndexedDB ${IDB_NAME}, path ${DB_NAME}`); vfs = new IDBBatchAtomicVFS(IDB_NAME); // @ts-ignore await importDatabase(vfs, DB_NAME, event.target.files[0].stream()); log('Import complete'); + + log('Verifying database integrity'); + const url = new URL('./verifier.js', location.href); + url.searchParams.set('idb', IDB_NAME); + url.searchParams.set('db', DB_NAME); + const worker = new Worker(url, { type: 'module' }); + await new Promise(resolve => { + worker.addEventListener('message', ({data}) => { + resolve(); + for (const row of data) { + log(`integrity result: ${row}`); + } + worker.terminate(); + }); + }); + log('Verification complete'); } catch (e) { log(e.toString()); throw e; @@ -34,6 +50,7 @@ async function importDatabase(vfs, path, stream) { const reader = stream.getReader(); // Read at least the file header fields we need. + log('Reading file header...'); while (chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0) < 32) { const { done, value } = await reader.read(); if (done) throw new Error('Unexpected end of file'); @@ -55,7 +72,9 @@ async function importDatabase(vfs, path, stream) { // Extract page parameters. const pageSize = (field => field === 1 ? 65536 : field)(header.getUint16(16)); const pageCount = header.getUint32(28); + log(`${pageCount} pages, ${pageSize} bytes each, ${pageCount * pageSize} bytes total`); + log('Copying pages...'); for (let i = 0; i < pageCount; ++i) { // Read enough chunks to produce the next page. while (chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0) < pageSize) { @@ -92,10 +111,11 @@ async function importDatabase(vfs, path, stream) { const onFinally = []; try { - // Delete any existing file. - await vfs.xDelete(path, 0); + log(`Deleting ${path}...`); + await vfs.xDelete(path, 1); // Create the file. + log(`Creating ${path}...`); const fileId = 1234; const flags = VFS.SQLITE_OPEN_MAIN_DB | VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE; await check(vfs.xOpen(path, fileId, flags, new DataView(new ArrayBuffer(4)))); diff --git a/demo/file/verifier.js b/demo/file/verifier.js new file mode 100644 index 00000000..1a53e864 --- /dev/null +++ b/demo/file/verifier.js @@ -0,0 +1,25 @@ +import SQLiteESMFactory from '../../dist/wa-sqlite-async.mjs'; +import * as SQLite from '../../src/sqlite-api.js'; +import { IDBBatchAtomicVFS } from '../../src/examples/IDBBatchAtomicVFS.js'; + +const SEARCH_PARAMS = new URLSearchParams(location.search); +const IDB_NAME = SEARCH_PARAMS.get('idb') ?? 'sqlite-vfs'; +const DB_NAME = SEARCH_PARAMS.get('db') ?? 'sqlite.db'; + +(async function() { + const module = await SQLiteESMFactory(); + const sqlite3 = SQLite.Factory(module); + + const vfs = new IDBBatchAtomicVFS(IDB_NAME); + sqlite3.vfs_register(vfs, true); + + const db = await sqlite3.open_v2(DB_NAME, SQLite.SQLITE_OPEN_READWRITE, IDB_NAME); + + const results = [] + await sqlite3.exec(db, 'PRAGMA integrity_check;', (row, columns) => { + results.push(row[0]); + }); + await sqlite3.close(db); + + postMessage(results); +})(); \ No newline at end of file