sqlite3.initWorker1API = function(){
'use strict';
const toss = (...args)=>{throw new Error(args.join(' '))};
- if('function' !== typeof importScripts){
- toss("Cannot initalize the sqlite3 worker API in the main thread.");
+ if(self.window === self || 'function' !== typeof importScripts){
+ toss("initWorker1API() must be run from a Worker thread.");
}
const self = this.self;
const sqlite3 = this.sqlite3 || toss("Missing this.sqlite3 object.");
- const SQLite3 = sqlite3.oo1 || toss("Missing this.sqlite3.oo1 OO API.");
- const DB = SQLite3.DB;
+ const DB = sqlite3.oo1.DB;
/**
Returns the app-wide unique ID for the given db, creating one if
--- /dev/null
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
+ <title>Hello, sqlite3</title>
+ <style>
+ .warning, .error {color: red}
+ .error {background-color: yellow}
+ body {
+ display: flex;
+ flex-direction: column;
+ font-family: monospace;
+ white-space: break-spaces;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>1-2-sqlite3 worker demo</h2>
+ <script>(function(){
+ const logHtml = function(cssClass,...args){
+ const ln = document.createElement('div');
+ if(cssClass) ln.classList.add(cssClass);
+ ln.append(document.createTextNode(args.join(' ')));
+ document.body.append(ln);
+ };
+ const w = new Worker("demo-123.js");
+ w.onmessage = function({data}){
+ switch(data.type){
+ case 'log':
+ logHtml(data.payload.cssClass, ...data.payload.args);
+ break;
+ default:
+ logHtml('error',"Unhandled message:",data.type);
+ };
+ };
+ })();</script>
+ </body>
+</html>
--- /dev/null
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
+ <title>Hello, sqlite3</title>
+ <style>
+ .warning, .error {color: red}
+ .error {background-color: yellow}
+ body {
+ display: flex;
+ flex-direction: column;
+ font-family: monospace;
+ white-space: break-spaces;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>1-2-sqlite3 demo</h2>
+ <script src="sqlite3.js"></script>
+ <script src="demo-123.js"></script>
+ </body>
+</html>
/*
- 2022-08-16
+ 2022-09-19
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
***********************************************************************
- A basic demonstration of the SQLite3 OO API #1, shorn of assertions
- and the like to improve readability.
+ A basic demonstration of the SQLite3 OO API.
*/
'use strict';
(function(){
- const toss = function(...args){throw new Error(args.join(' '))};
- const debug = console.debug.bind(console),
- log = console.log.bind(console),
- warn = console.warn.bind(console),
- error = console.error.bind(console);
+ /**
+ Set up our output channel differently depending
+ on whether we are running in a worker thread or
+ the main (UI) thread.
+ */
+ let logHtml;
+ if(self.window === self /* UI thread */){
+ logHtml = function(cssClass,...args){
+ const ln = document.createElement('div');
+ if(cssClass) ln.classList.add(cssClass);
+ ln.append(document.createTextNode(args.join(' ')));
+ document.body.append(ln);
+ };
+ }else{ /* Worker thread */
+ logHtml = function(cssClass,...args){
+ postMessage({
+ type:'log',
+ payload:{cssClass, args}
+ });
+ };
+ }
+ const log = (...args)=>logHtml('',...args);
+ const warn = (...args)=>logHtml('warning',...args);
+ const error = (...args)=>logHtml('error',...args);
const demo1 = function(sqlite3){
- const capi = sqlite3.capi,
- oo = sqlite3.oo1,
- wasm = capi.wasm;
-
- const dbName = (
- 0 ? "" : capi.sqlite3_web_persistent_dir()
- )+"/mydb.sqlite3"
- if(0 && capi.sqlite3_web_persistent_dir()){
- capi.wasm.sqlite3_wasm_vfs_unlink(dbName);
- }
- const db = new oo.DB(dbName);
- log("db =",db.filename);
+ const capi = sqlite3.capi/*C-style API*/,
+ oo = sqlite3.oo1/*high-level OO API*/;
+ log("sqlite3 version",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
+ const db = new oo.DB("/mydb.sqlite3");
+ log("transient b =",db.filename);
/**
Never(!) rely on garbage collection to clean up DBs and
(especially) statements. Always wrap their lifetimes in
- try/finally construct...
+ try/finally construct, as demonstrated below. By and large,
+ client code can avoid lifetime-related complications of
+ prepared statement objects by using the DB.exec() method for
+ SQL execution.
*/
try {
log("Create a table...");
// ... numerous other options ...
});
// SQL can be either a string or a byte array
+ // or an array of strings which get concatenated
+ // together as-is (so be sure to end each statement
+ // with a semicolon).
log("Insert some data using exec()...");
let i;
- for( i = 1; i <= 5; ++i ){
+ for( i = 20; i <= 25; ++i ){
db.exec({
sql: "insert into t(a,b) values (?,?)",
// bind by parameter index...
db.exec({
sql: "insert into t(a,b) values ($a,$b)",
// bind by parameter name...
- bind: {$a: i * 3, $b: i * 4}
+ bind: {$a: i * 10, $b: i * 20}
});
}
sql: "select a as aa, b as bb from t order by aa limit 3",
rowMode: 'object',
callback: function(row){
- log("row ",++this.counter,"=",row);
+ log("row ",++this.counter,"=",JSON.stringify(row));
}.bind({counter: 0})
});
}.bind({counter: 0})
});
+ log("Query data with exec() using rowMode $COLNAME (result column name)...");
+ db.exec({
+ sql: "select a a, b from t order by a limit 3",
+ rowMode: '$a',
+ callback: function(value){
+ log("row ",++this.counter,"a =",value);
+ }.bind({counter: 0})
+ });
+
log("Query data with exec() without a callback...");
let resultRows = [];
db.exec({
rowMode: 'object',
resultRows: resultRows
});
- log("Result rows:",resultRows);
+ log("Result rows:",JSON.stringify(resultRows,undefined,2));
log("Create a scalar UDF...");
db.createFunction({
});
log("Result column names:",columnNames);
- if(0){
- warn("UDF will throw because of incorrect arg count...");
+ try{
+ log("The following use of the twice() UDF will",
+ "fail because of incorrect arg count...");
db.exec("select twice(1,2,3)");
+ }catch(e){
+ warn("Got expected exception:",e.message);
}
try {
log("In savepoint: count(*) from t =",db.selectValue("select count(*) from t"));
D.savepoint(function(DD){
const rows = [];
- D.exec({
+ DD.exec({
sql: ["insert into t(a,b) values(99,100);",
"select count(*) from t"],
rowMode: 0,
throw e;
}
}
-
}finally{
db.close();
}
+ log("That's all, folks!");
+
/**
- Misc. DB features:
+ Some of the features of the OO API not demonstrated above...
- get change count (total or statement-local, 32- or 64-bit)
- - get its file name
- - selectValue() takes SQL and returns first column of first row.
+ - get a DB's file name
Misc. Stmt features:
*/
}/*demo1()*/;
- const runDemos = function(Module){
- //log("Module.sqlite3",Module);
- const sqlite3 = Module.sqlite3,
- capi = sqlite3.capi;
- log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
- log("sqlite3 namespace:",sqlite3);
+ log("Loading and initializing sqlite3 module...");
+ if(self.window!==self) /*worker thread*/{
+ importScripts("sqlite3.js");
+ }
+ self.sqlite3InitModule({
+ // We can redirect any stdout/stderr from the module
+ // like so...
+ print: log,
+ printErr: error
+ }).then(function(EmscriptenModule){
+ log("Done initializing. Running demo...");
try {
- demo1(sqlite3);
+ demo1(EmscriptenModule.sqlite3);
}catch(e){
error("Exception:",e.message);
- throw e;
}
- };
-
- //self.sqlite3TestModule.sqlite3ApiConfig.persistentDirName = "/hi";
- self.sqlite3TestModule.initSqlite3().then(runDemos);
+ });
})();
+++ /dev/null
-<!doctype html>
-<html lang="en-us">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
- <link rel="stylesheet" href="common/emscripten.css"/>
- <link rel="stylesheet" href="common/testing.css"/>
- <title>sqlite3-api OO #1 Demo</title>
- </head>
- <body>
- <header id='titlebar'><span>sqlite3-api OO #1 Demo</span></header>
- <!-- emscripten bits -->
- <figure id="module-spinner">
- <div class="spinner"></div>
- <div class='center'><strong>Initializing app...</strong></div>
- <div class='center'>
- On a slow internet connection this may take a moment. If this
- message displays for "a long time", intialization may have
- failed and the JavaScript console may contain clues as to why.
- </div>
- </figure>
- <div class="emscripten" id="module-status">Downloading...</div>
- <div class="emscripten">
- <progress value="0" max="100" id="module-progress" hidden='1'></progress>
- </div><!-- /emscripten bits -->
- <div>Most stuff on this page happens in the dev console.</div>
- <hr>
- <div id='test-output'></div>
- <script src="sqlite3.js"></script>
- <script src="common/SqliteTestUtil.js"></script>
- <script src="demo-oo1.js"></script>
- </body>
-</html>
the web server emit the so-called COOP and COEP headers. The
default build of althttpd <em>does not</em>.
</li>
+ <li>Any OPFS-related pages require very recent
+ version of Chrome or Chromium (v102 at least, possibly
+ newer). OPFS support in the other major browsers is
+ pending.</li>
<li>Whether or not WASMFS/OPFS support is enabled on any given
page may depend on build-time options which are <em>off by
default</em> because they currently (as of 2022-09-08) break
- with Worker-based pages.
+ with Worker-based pages. Similarly, WASMFS does not work on
+ some platforms, e.g. Raspberry Pi 4.
</li>
</ul>
</div>
<div>The tests...
<ul id='test-list'>
+ <li><a href='demo-123.html'>demo-123</a> provides a
+ no-nonsense example of adding sqlite3 support to a
+ web page. </li>
+ <li><a href='demo-123-worker.html'>demo-123-worker</a> is the
+ same as <code>demo-123</code> but loads and run sqlite3 from
+ a Worker thread.</li>
<li><a href='testing1.html'>testing1</a>: sanity tests of the core APIs and surrounding utility code.</li>
<li><a href='testing2.html'>testing2</a>: Worker-based test of OO API #1.</li>
<li><a href='testing-worker1-promiser.html'>testing-worker1-promiser</a>:
tests for the Promise-based wrapper of the Worker-based API.</li>
- <li><a href='demo-oo1.html'>demo-oo1</a>: demonstration of the OO API #1.</li>
<li><a href='batch-runner.html'>batch-runner</a>: runs batches of SQL exported from speedtest1.</li>
<li><a href='batch-runner-kvvfs.html'>batch-runner-kvvfs</a>: KVVFS-specific variant of batch-runner.html.</li>
<li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li>
arguments when the worker fires its initial
'sqlite3-api'/'worker1-ready' message, which it does when
sqlite3.initWorker1API() completes its initialization. This is
- the simplest way to tell the worker to kick of work at the
+ the simplest way to tell the worker to kick off work at the
earliest opportunity.
- `onerror` (optional): a callback to pass error-type events from
are not handled by this proxy. Ideally that "should" never
happen, as this proxy aims to handle all known message types.
- - `generateMessageId` (optional): a function which, when passed
- an about-to-be-posted message object, generates a _unique_
- message ID for the message, which this API then assigns as the
- messageId property of the message. It _must_ generate unique
- IDs so that dispatching can work. If not defined, a default
- generator is used.
+ - `generateMessageId` (optional): a function which, when passed an
+ about-to-be-posted message object, generates a _unique_ message ID
+ for the message, which this API then assigns as the messageId
+ property of the message. It _must_ generate unique IDs on each call
+ so that dispatching can work. If not defined, a default generator
+ is used (which should be sufficient for most or all cases).
- `dbId` (optional): is the database ID to be used by the
worker. This must initially be unset or a falsy value. The
first `open` message sent to the worker will cause this config
entry to be assigned to the ID of the opened database. That ID
- "should" be set as the `dbId` property of the message sent in
+ "should" be set as the `dbId` property of the messages sent in
future requests, so that the worker uses that database.
However, if the worker is not given an explicit dbId, it will
use the first-opened database by default. If client code needs
- `debug` (optional): a console.debug()-style function for logging
information about messages.
-
This function returns a stateful factory function with the
following interfaces:
The first form expects the "type" and "args" values for a Worker
message. The second expects an object in the form {type:...,
args:...} plus any other properties the client cares to set. This
- function will always set the messageId property on the object,
- even if it's already set, and will set the dbId property to
- config.dbId if it is _not_ set in the message object.
+ function will always set the `messageId` property on the object,
+ even if it's already set, and will set the `dbId` property to
+ `config.dbId` if it is _not_ set in the message object.
The function throws on error.
- The function installs a temporarily message listener, posts a
+ The function installs a temporary message listener, posts a
message to the configured Worker, and handles the message's
response via the temporary message listener. The then() callback
of the returned Promise is passed the `message.data` property from
```
const config = {...};
- const eventPromiser = sqlite3Worker1Promiser(config);
- eventPromiser('open', {filename:"/foo.db"}).then(function(msg){
+ const sq3Promiser = sqlite3Worker1Promiser(config);
+ sq3Promiser('open', {filename:"/foo.db"}).then(function(msg){
console.log("open response",msg); // => {type:'open', result: {filename:'/foo.db'}, ...}
// Recall that config.dbId will be set for the first 'open'
// call and cleared for a matching 'close' call.
});
- eventPromiser({type:'close'}).then((msg)=>{
- console.log("open response",msg); // => {type:'open', result: {filename:'/foo.db'}, ...}
+ sq3Promiser({type:'close'}).then((msg)=>{
+ console.log("close response",msg); // => {type:'close', result: {filename:'/foo.db'}, ...}
// Recall that config.dbId will be used by default for the message's dbId if
// none is explicitly provided, and a 'close' op will clear config.dbId if it
// closes that exact db.
-C Disable\sbuild\sof\swasmfs-using\scomponents\son\saarch64\s(ARM),\sas\swasmfs\swon't\sbuild\sthere.
-D 2022-09-19T00:40:53.768
+C Rename\sdemo-oo1.*\sto\sdemo-123.*\sand\sadd\sdemo-123-worker.html,\swhich\sruns\sthe\ssame\sdemo\svia\sa\sWorker.\sDoc\stypo\sfixes.
+D 2022-09-19T03:57:31.704
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/wasm/api/sqlite3-api-oo1.js 2d13dddf0d2b4168a9249f124134d37924331e5b55e05dba18b6d661fbeefe48
F ext/wasm/api/sqlite3-api-opfs.js 4090abf4e16b460543ff665e96822048e37a2703e0ba46a01fed3a15c024c034
F ext/wasm/api/sqlite3-api-prologue.js 4e3e26880d444000cca1b4f3ddfa9d49581dfecd1de9426080239ecc208c447d
-F ext/wasm/api/sqlite3-api-worker1.js e8456bd9b93eab297d065b25cb7a253835f606f9349383f2aa5c585e8d3b3aef
+F ext/wasm/api/sqlite3-api-worker1.js ee4cf149cbacb63d06b536674f822aa5088b7e022cdffc69f1f36cebe2f9fea0
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 4130e2df9587f4e4c3afc04c3549d682c8a5c0cfe5b22819a0a86edb7f01b9bd
F ext/wasm/batch-runner-kvvfs.html ef3b2f553abad4f17a2a29ce6526023793a88e8597b7a24b8c7855a030b90a16
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
F ext/wasm/common/whwasmutil.js f7282ef36c9625330d4e6e82d1beec6678cd101e95e7108cd85db587a788c145
-F ext/wasm/demo-oo1.html 75646855b38405d82781246fd08c852a2b3bee05dd9f0fe10ab655a8cffb79aa
-F ext/wasm/demo-oo1.js 477f230cce3455e701431436d892d8c6bfea2bdf1ddcdd32a273e2f4bb339801
+F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f
+F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4 w ext/wasm/demo-oo1.html
+F ext/wasm/demo-123.js 2c5e7775339624819067fd169d202004faeddc9d8ef452dd1f95aa4b3972a5b2 w ext/wasm/demo-oo1.js
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/fiddle/fiddle-worker.js bccf46045be8824752876f3eec01c223be0616ccac184bffd0024cfe7a3262b8
F ext/wasm/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
F ext/wasm/fiddle/fiddle.js 4ffcfc9a235beebaddec689a549e9e0dfad6dca5c1f0b41f03468d7e76480686
-F ext/wasm/index.html d698cc021c25ca940f67805c2cc2848c303705d98b4c4f9f55565b9a9c37d2bb
+F ext/wasm/index.html aed40adf52598a353e27e50480d53e59a5e75e9ba889f7d8bb2fda45a0a91c3b
F ext/wasm/jaccwabyt/jaccwabyt.js 0d7f32817456a0f3937fcfd934afeb32154ca33580ab264dab6c285e6dbbd215
F ext/wasm/jaccwabyt/jaccwabyt.md 447cc02b598f7792edaa8ae6853a7847b8178a18ed356afacbdbf312b2588106
F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/sqlite3-opfs-async-proxy.js 6e89e1af7c616afdd877cbcf5d0ec3d5f47ba252b9a19e696140b9495dc1e653
-F ext/wasm/sqlite3-worker1-promiser.js 92b8da5f38439ffec459a8215775d30fa498bc0f1ab929ff341fc3dd479660b9
+F ext/wasm/sqlite3-worker1-promiser.js 4fd0465688a28a75f1d4ee4406540ba494f49844e3cad0670d0437a001943365
F ext/wasm/sqlite3-worker1.js 0c1e7626304543969c3846573e080c082bf43bcaa47e87d416458af84f340a9e
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
F ext/wasm/test-opfs-vfs.js 753c6b86dd8ce0813121add44726a038ba1b83acebdc8414189cb163faf23e6d
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 26e625d05d9820033b23536f18ad3ddc59ed712ad507d4b0c7fe88abd15d2be8
-R 21836a2cce93d296ed51495c106454e4
+P 9a9eeebc2c27b734041089131b4952d7c0440df48ef32f355641aca61d4b30a0
+R 8192577a9e0361d9ed4a520726bee437
U stephan
-Z 476194268503f5b6d3efae07b951acc1
+Z 37e4874c91d49fe3eefc7a1b4b57c686
# Remove this line to create a well-formed Fossil manifest.
-9a9eeebc2c27b734041089131b4952d7c0440df48ef32f355641aca61d4b30a0
\ No newline at end of file
+2e4a005bd35424caeaa99ace23162cf79e2ebdb159475ffad92b85dc864ad764
\ No newline at end of file