4 The author disclaims copyright to this source code. In place of a
5 legal notice, here is a blessing:
7 * May you do good and not evil.
8 * May you find forgiveness for yourself and forgive others.
9 * May you share freely, never taking more than you give.
11 ***********************************************************************
13 Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based
14 proxy for for the sqlite3 Worker #1 API.
16 //#if target=es6-module
17 import {default as promiserFactory
} from "./jswasm/sqlite3-worker1-promiser.mjs";
20 const promiserFactory
= globalThis
.sqlite3Worker1Promiser
.v2
;
21 delete globalThis
.sqlite3Worker1Promiser
;
24 const T
= globalThis
.SqliteTestUtil
;
25 const eOutput
= document
.querySelector('#test-output');
26 const warn
= console
.warn
.bind(console
);
27 const error
= console
.error
.bind(console
);
28 const log
= console
.log
.bind(console
);
29 const logHtml
= async
function(cssClass
,...args
){
30 log
.apply(this, args
);
31 const ln
= document
.createElement('div');
32 if(cssClass
) ln
.classList
.add(cssClass
);
33 ln
.append(document
.createTextNode(args
.join(' ')));
38 const testCount
= async ()=>{
39 logHtml("","Total test count:",T
.counter
+". Total time =",(performance
.now() - startTime
),"ms");
42 const promiserConfig
= {
43 //#ifnot target=es6-module
45 The v1 interfaces uses an onready function. The v2 interface optionally
46 accepts one but does not require it. If provided, it is called _before_
47 the promise is resolved, and the promise is rejected if onready() throws.
50 /* f === the function returned by promiserFactory().
51 Ostensibly (f === workerPromise) but this function is
52 called before the promiserFactory() Promise resolves, so
53 before workerPromise is set. */
54 console
.warn("This is the v2 interface - you don't need an onready() function.");
57 debug
: 1 ? undefined : (...args
)=>console
.debug('worker debug',...args
),
58 onunhandled: function(ev
){
59 error("Unhandled worker message:",ev
.data
);
61 onerror: function(ev
){
62 error("worker1 error:",ev
);
65 const workerPromise
= await
promiserFactory(promiserConfig
)
67 console
.log("Init complete. Starting tests momentarily.");
68 globalThis
.sqlite3TestModule
.setStatus(null)/*hide the HTML-side is-loading spinner*/;
72 const wtest
= async
function(msgType
, msgArgs
, callback
){
73 if(2===arguments
.length
&& 'function'===typeof msgArgs
){
78 ? workerPromise({type
: msgType
, args
:msgArgs
})
79 : workerPromise(msgType
, msgArgs
);
80 return callback
? p
.then(callback
).finally(testCount
) : p
;
84 const runTests
= async
function(){
85 const dbFilename
= '/testing2.sqlite3';
86 startTime
= performance
.now();
88 await
wtest('config-get', (ev
)=>{
90 log('sqlite3.config subset:', r
);
91 T
.assert('boolean' === typeof r
.bigIntEnabled
);
95 "Sending 'open' message and waiting for its response before continuing...");
99 simulateError
: 0 /* if true, fail the 'open' */,
102 log("then open result",r
);
103 T
.assert(ev
.dbId
=== r
.dbId
)
104 .assert(ev
.messageId
)
105 .assert('string' === typeof r
.vfs
);
106 promiserConfig
.dbId
= ev
.dbId
;
110 const runTests2
= async
function(){
111 const mustNotReach
= ()=>toss("This is not supposed to be reached.");
114 sql
: ["create table t(a,b)",
115 "insert into t(a,b) values(1,2),(3,4),(5,6)"
117 resultRows
: [], columnNames
: [],
118 countChanges
: sqConfig
.bigIntEnabled
? 64 : true
121 T
.assert(0===ev
.resultRows
.length
)
122 .assert(0===ev
.columnNames
.length
)
123 .assert(sqConfig
.bigIntEnabled
124 ? (3n
===ev
.changeCount
)
125 : (3===ev
.changeCount
));
129 sql
: 'select a a, b b from t order by a',
130 resultRows
: [], columnNames
: [],
133 T
.assert(3===ev
.resultRows
.length
)
134 .assert(1===ev
.resultRows
[0][0])
135 .assert(6===ev
.resultRows
[2][1])
136 .assert(2===ev
.columnNames
.length
)
137 .assert('b'===ev
.columnNames
[1]);
141 sql
: 'select a a, b b from t order by a',
142 resultRows
: [], columnNames
: [],
147 T
.assert(3===ev
.resultRows
.length
)
148 .assert(1===ev
.resultRows
[0].a
)
149 .assert(6===ev
.resultRows
[2].b
)
150 .assert(0===ev
.changeCount
);
155 {sql
:'intentional_error'},
158 warn("Intentional error:",e
);
162 sql
:'select 1 union all select 3',
166 T
.assert(2 === ev
.resultRows
.length
)
167 .assert(1 === ev
.resultRows
[0][0])
168 .assert(3 === ev
.resultRows
[1][0])
169 .assert(undefined === ev
.changeCount
);
172 const resultRowTest1
= function f(ev
){
173 if(undefined === f
.counter
) f
.counter
= 0;
174 if(null === ev
.rowNumber
){
175 /* End of result set. */
176 T
.assert(undefined === ev
.row
)
177 .assert(2===ev
.columnNames
.length
)
178 .assert('a'===ev
.columnNames
[0])
179 .assert('B'===ev
.columnNames
[1]);
181 T
.assert(ev
.rowNumber
> 0);
184 log("exec() result row:",ev
);
185 T
.assert(null === ev
.rowNumber
|| 'number' === typeof ev
.row
.B
);
188 sql
: 'select a a, b B from t order by a limit 3',
189 callback
: resultRowTest1
,
192 T
.assert(3===resultRowTest1
.counter
);
193 resultRowTest1
.counter
= 0;
196 const resultRowTest2
= function f(ev
){
197 if(null === ev
.rowNumber
){
198 /* End of result set. */
199 T
.assert(undefined === ev
.row
)
200 .assert(1===ev
.columnNames
.length
)
201 .assert('a'===ev
.columnNames
[0])
203 T
.assert(ev
.rowNumber
> 0);
204 f
.counter
= ev
.rowNumber
;
206 log("exec() result row:",ev
);
207 T
.assert(null === ev
.rowNumber
|| 'number' === typeof ev
.row
);
210 sql
: 'select a a from t limit 3',
211 callback
: resultRowTest2
,
214 T
.assert(3===resultRowTest2
.counter
);
217 const resultRowTest3
= function f(ev
){
218 if(null === ev
.rowNumber
){
219 T
.assert(3===ev
.columnNames
.length
)
220 .assert('foo'===ev
.columnNames
[0])
221 .assert('bar'===ev
.columnNames
[1])
222 .assert('baz'===ev
.columnNames
[2]);
224 f
.counter
= ev
.rowNumber
;
225 T
.assert('number' === typeof ev
.row
);
229 sql
: "select 'foo' foo, a bar, 'baz' baz from t limit 2",
230 callback
: resultRowTest3
,
234 log("exec() result row:",ev
);
235 T
.assert(2===resultRowTest3
.counter
);
240 'pragma foreign_keys=0;',
241 // ^^^ arbitrary query with no result columns
242 'select a, b from t order by a desc; select a from t;'
243 // exec() only honors SELECT results from the first
244 // statement with result columns (regardless of whether
250 const rows
= ev
.result
.resultRows
;
251 T
.assert(3===rows
.length
).
255 await
wtest('exec',{sql
: 'delete from t where a>3'});
258 sql
: 'select count(a) from t',
262 T
.assert(1===ev
.resultRows
.length
)
263 .assert(2===ev
.resultRows
[0][0]);
266 await
wtest('export', function(ev
){
268 T
.assert('string' === typeof ev
.filename
)
269 .assert(ev
.byteArray
instanceof Uint8Array
)
270 .assert(ev
.byteArray
.length
> 1024)
271 .assert('application/x-sqlite3' === ev
.mimetype
);
274 /***** close() tests must come last. *****/
275 await
wtest('close',{},function(ev
){
276 T
.assert('string' === typeof ev
.result
.filename
);
279 await
wtest('close', (ev
)=>{
280 T
.assert(undefined === ev
.result
.filename
);
281 }).finally(()=>logHtml('',"That's all, folks!"));