@livestore/wa-sqlite 1.0.1-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/wa-sqlite-async.mjs +16 -0
- package/dist/wa-sqlite-async.wasm +0 -0
- package/dist/wa-sqlite-jspi.mjs +16 -0
- package/dist/wa-sqlite-jspi.wasm +0 -0
- package/dist/wa-sqlite.mjs +16 -0
- package/dist/wa-sqlite.wasm +0 -0
- package/package.json +45 -0
- package/src/FacadeVFS.js +508 -0
- package/src/VFS.js +222 -0
- package/src/WebLocksMixin.js +412 -0
- package/src/examples/AccessHandlePoolVFS.js +458 -0
- package/src/examples/IDBBatchAtomicVFS.js +820 -0
- package/src/examples/IDBMirrorVFS.js +875 -0
- package/src/examples/MemoryAsyncVFS.js +100 -0
- package/src/examples/MemoryVFS.js +176 -0
- package/src/examples/OPFSAdaptiveVFS.js +437 -0
- package/src/examples/OPFSAnyContextVFS.js +300 -0
- package/src/examples/OPFSCoopSyncVFS.js +590 -0
- package/src/examples/OPFSPermutedVFS.js +1214 -0
- package/src/examples/README.md +89 -0
- package/src/examples/tag.js +82 -0
- package/src/sqlite-api.js +914 -0
- package/src/sqlite-constants.js +275 -0
- package/src/types/globals.d.ts +60 -0
- package/src/types/index.d.ts +1302 -0
- package/src/types/tsconfig.json +6 -0
- package/test/AccessHandlePoolVFS.test.js +27 -0
- package/test/IDBBatchAtomicVFS.test.js +97 -0
- package/test/IDBMirrorVFS.test.js +27 -0
- package/test/MemoryAsyncVFS.test.js +27 -0
- package/test/MemoryVFS.test.js +27 -0
- package/test/OPFSAdaptiveVFS.test.js +27 -0
- package/test/OPFSAnyContextVFS.test.js +27 -0
- package/test/OPFSCoopSyncVFS.test.js +27 -0
- package/test/OPFSPermutedVFS.test.js +27 -0
- package/test/TestContext.js +96 -0
- package/test/WebLocksMixin.test.js +521 -0
- package/test/api.test.js +49 -0
- package/test/api_exec.js +89 -0
- package/test/api_misc.js +63 -0
- package/test/api_statements.js +426 -0
- package/test/callbacks.test.js +373 -0
- package/test/sql.test.js +64 -0
- package/test/sql_0001.js +49 -0
- package/test/sql_0002.js +52 -0
- package/test/sql_0003.js +83 -0
- package/test/sql_0004.js +81 -0
- package/test/sql_0005.js +76 -0
- package/test/test-worker.js +204 -0
- package/test/vfs_xAccess.js +2 -0
- package/test/vfs_xClose.js +52 -0
- package/test/vfs_xOpen.js +91 -0
- package/test/vfs_xRead.js +38 -0
- package/test/vfs_xWrite.js +36 -0
package/test/api_misc.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as SQLite from '../src/sqlite-api.js';
|
|
2
|
+
|
|
3
|
+
export function api_misc(context) {
|
|
4
|
+
describe('libversion', function() {
|
|
5
|
+
let proxy, sqlite3, db;
|
|
6
|
+
beforeEach(async function() {
|
|
7
|
+
proxy = await context.create();
|
|
8
|
+
sqlite3 = proxy.sqlite3;
|
|
9
|
+
db = await sqlite3.open_v2('demo');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(async function() {
|
|
13
|
+
await sqlite3.close(db);
|
|
14
|
+
await context.destroy(proxy);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return the library version', async function() {
|
|
18
|
+
const versionString = await sqlite3.libversion();
|
|
19
|
+
expect(versionString).toMatch(/^\d+\.\d+\.\d+$/);
|
|
20
|
+
|
|
21
|
+
const components = versionString.split('.')
|
|
22
|
+
.map((component, i) => {
|
|
23
|
+
return i ? component.padStart(3, '0') : component;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const versionNumber = await sqlite3.libversion_number();
|
|
27
|
+
expect(versionNumber.toString()).toEqual(components.join(''));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('limit', function() {
|
|
32
|
+
let proxy, sqlite3, db;
|
|
33
|
+
beforeEach(async function() {
|
|
34
|
+
proxy = await context.create();
|
|
35
|
+
sqlite3 = proxy.sqlite3;
|
|
36
|
+
db = await sqlite3.open_v2('demo');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(async function() {
|
|
40
|
+
await sqlite3.close(db);
|
|
41
|
+
await context.destroy(proxy);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should constrain usage', async function() {
|
|
45
|
+
const sql = `
|
|
46
|
+
SELECT 1, 2, 3, 4, 5, 6;
|
|
47
|
+
`.trim();
|
|
48
|
+
|
|
49
|
+
let rc;
|
|
50
|
+
await expectAsync(sqlite3.exec(db, sql)).toBeResolvedTo(SQLite.SQLITE_OK);
|
|
51
|
+
|
|
52
|
+
rc = await sqlite3.limit(db, SQLite.SQLITE_LIMIT_COLUMN, 5);
|
|
53
|
+
expect(rc).toBeGreaterThan(0);
|
|
54
|
+
|
|
55
|
+
await expectAsync(sqlite3.exec(db, sql)).toBeRejectedWithError(/too many columns/);
|
|
56
|
+
|
|
57
|
+
rc = await sqlite3.limit(db, SQLite.SQLITE_LIMIT_COLUMN, rc);
|
|
58
|
+
expect(rc).toEqual(5);
|
|
59
|
+
|
|
60
|
+
await expectAsync(sqlite3.exec(db, sql)).toBeResolvedTo(SQLite.SQLITE_OK);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import * as SQLite from '../src/sqlite-api.js';
|
|
2
|
+
|
|
3
|
+
export function api_statements(context) {
|
|
4
|
+
describe('statements', function() {
|
|
5
|
+
let proxy, sqlite3, db;
|
|
6
|
+
beforeEach(async function() {
|
|
7
|
+
proxy = await context.create();
|
|
8
|
+
sqlite3 = proxy.sqlite3;
|
|
9
|
+
db = await sqlite3.open_v2('demo');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(async function() {
|
|
13
|
+
await sqlite3.close(db);
|
|
14
|
+
await context.destroy(proxy);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should iterate', async function() {
|
|
18
|
+
const sql = [
|
|
19
|
+
'PRAGMA journal_mode',
|
|
20
|
+
'CREATE TABLE t(x)',
|
|
21
|
+
'SELECT * FROM sqlite_master'
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
let count = 0;
|
|
25
|
+
for await (const stmt of i(sqlite3.statements(db, sql.join(';\n')))) {
|
|
26
|
+
// We should be able to retrieve each parsed statement.
|
|
27
|
+
const query = await sqlite3.sql(stmt);
|
|
28
|
+
expect(query.includes(sql[count++])).toBeTrue();
|
|
29
|
+
}
|
|
30
|
+
expect(count).toEqual(sql.length);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should bind blob', async function() {
|
|
34
|
+
let rc;
|
|
35
|
+
const sql = 'SELECT ?';
|
|
36
|
+
const value = new Uint8Array([1, 2, 3, 4, 5]);
|
|
37
|
+
|
|
38
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
39
|
+
rc = await sqlite3.bind_blob(stmt, 1, value);
|
|
40
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
41
|
+
|
|
42
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
43
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
44
|
+
|
|
45
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
46
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_BLOB);
|
|
47
|
+
|
|
48
|
+
const blobTyped = await sqlite3.column_blob(stmt, 0);
|
|
49
|
+
expect([...blobTyped]).toEqual([...value]);
|
|
50
|
+
|
|
51
|
+
const blobVariant = await sqlite3.column(stmt, 0);
|
|
52
|
+
expect([...blobVariant]).toEqual([...value]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
57
|
+
// Comlink intercepts the 'bind' property so use an alias.
|
|
58
|
+
rc = await sqlite3.bind$(stmt, 1, value);
|
|
59
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
60
|
+
|
|
61
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
62
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
63
|
+
|
|
64
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
65
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_BLOB);
|
|
66
|
+
|
|
67
|
+
const blob = await sqlite3.column_blob(stmt, 0);
|
|
68
|
+
expect([...blob]).toEqual([...value]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should bind double', async function() {
|
|
74
|
+
let rc;
|
|
75
|
+
const sql = 'SELECT ?';
|
|
76
|
+
const value = Math.PI;
|
|
77
|
+
|
|
78
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
79
|
+
rc = await sqlite3.bind_double(stmt, 1, value);
|
|
80
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
81
|
+
|
|
82
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
83
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
84
|
+
|
|
85
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
86
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_FLOAT);
|
|
87
|
+
expect(await sqlite3.column_double(stmt, 0)).toEqual(value);
|
|
88
|
+
expect(await sqlite3.column(stmt, 0)).toEqual(value);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
93
|
+
// Comlink intercepts the 'bind' property so use an alias.
|
|
94
|
+
rc = await sqlite3.bind$(stmt, 1, value);
|
|
95
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
96
|
+
|
|
97
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
98
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
99
|
+
|
|
100
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
101
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_FLOAT);
|
|
102
|
+
expect(await sqlite3.column_double(stmt, 0)).toEqual(value);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should bind int', async function() {
|
|
108
|
+
let rc;
|
|
109
|
+
const sql = 'SELECT ?';
|
|
110
|
+
const value = 42;
|
|
111
|
+
|
|
112
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
113
|
+
rc = await sqlite3.bind_int(stmt, 1, value);
|
|
114
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
115
|
+
|
|
116
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
117
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
118
|
+
|
|
119
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
120
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_INTEGER);
|
|
121
|
+
expect(await sqlite3.column_int(stmt, 0)).toEqual(value);
|
|
122
|
+
expect(await sqlite3.column(stmt, 0)).toEqual(value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
127
|
+
// Comlink intercepts the 'bind' property so use an alias.
|
|
128
|
+
rc = await sqlite3.bind$(stmt, 1, value);
|
|
129
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
130
|
+
|
|
131
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
132
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
133
|
+
|
|
134
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
135
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_INTEGER);
|
|
136
|
+
expect(await sqlite3.column_int(stmt, 0)).toEqual(value);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should bind int64', async function() {
|
|
142
|
+
let rc;
|
|
143
|
+
const sql = 'SELECT ?';
|
|
144
|
+
const value = BigInt(Number.MAX_SAFE_INTEGER) + 1n;
|
|
145
|
+
|
|
146
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
147
|
+
rc = await sqlite3.bind_int64(stmt, 1, value);
|
|
148
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
149
|
+
|
|
150
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
151
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
152
|
+
|
|
153
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
154
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_INTEGER);
|
|
155
|
+
expect(await sqlite3.column_int64(stmt, 0)).toEqual(value);
|
|
156
|
+
expect(await sqlite3.column(stmt, 0)).toEqual(value);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
161
|
+
// Comlink intercepts the 'bind' property so use an alias.
|
|
162
|
+
rc = await sqlite3.bind$(stmt, 1, value);
|
|
163
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
164
|
+
|
|
165
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
166
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
167
|
+
|
|
168
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
169
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_INTEGER);
|
|
170
|
+
expect(await sqlite3.column_int64(stmt, 0)).toEqual(value);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('should bind null', async function() {
|
|
176
|
+
let rc;
|
|
177
|
+
const sql = 'SELECT ?';
|
|
178
|
+
|
|
179
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
180
|
+
rc = await sqlite3.bind_null(stmt, 1);
|
|
181
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
182
|
+
await expectAsync(sqlite3.bind_parameter_count(stmt)).toBeResolvedTo(1);
|
|
183
|
+
|
|
184
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
185
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
186
|
+
|
|
187
|
+
await expectAsync(sqlite3.column_count(stmt)).toBeResolvedTo(1);
|
|
188
|
+
await expectAsync(sqlite3.column_type(stmt, 0)).toBeResolvedTo(SQLite.SQLITE_NULL);
|
|
189
|
+
await expectAsync(sqlite3.column(stmt, 0)).toBeResolvedTo(null);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
194
|
+
// Comlink intercepts the 'bind' property so use an alias.
|
|
195
|
+
rc = await sqlite3.bind$(stmt, 1, null);
|
|
196
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
197
|
+
|
|
198
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
199
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
200
|
+
|
|
201
|
+
await expectAsync(sqlite3.column_count(stmt)).toBeResolvedTo(1);
|
|
202
|
+
await expectAsync(sqlite3.column_type(stmt, 0)).toBeResolvedTo(SQLite.SQLITE_NULL);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('should bind text', async function() {
|
|
208
|
+
let rc;
|
|
209
|
+
const sql = 'SELECT ?';
|
|
210
|
+
const value = 'Hello, world!';
|
|
211
|
+
|
|
212
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
213
|
+
rc = await sqlite3.bind_text(stmt, 1, value);
|
|
214
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
215
|
+
|
|
216
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
217
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
218
|
+
|
|
219
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
220
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_TEXT);
|
|
221
|
+
expect(await sqlite3.column_text(stmt, 0)).toEqual(value);
|
|
222
|
+
expect(await sqlite3.column(stmt, 0)).toEqual(value);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
227
|
+
// Comlink intercepts the 'bind' property so use an alias.
|
|
228
|
+
rc = await sqlite3.bind$(stmt, 1, value);
|
|
229
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
230
|
+
|
|
231
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
232
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
233
|
+
|
|
234
|
+
expect(await sqlite3.column_count(stmt)).toEqual(1);
|
|
235
|
+
expect(await sqlite3.column_type(stmt, 0)).toEqual(SQLite.SQLITE_TEXT);
|
|
236
|
+
expect(await sqlite3.column_text(stmt, 0)).toEqual(value);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should bind collection array', async function() {
|
|
242
|
+
let rc;
|
|
243
|
+
const sql = 'VALUES (?, ?, ?, ?, ?)';
|
|
244
|
+
const cBlob = new Uint8Array([8, 6, 7, 5, 3, 0, 9]);
|
|
245
|
+
const cDouble = Math.PI;
|
|
246
|
+
const cInt = 42;
|
|
247
|
+
const cNull = null;
|
|
248
|
+
const cText = 'foobar';
|
|
249
|
+
|
|
250
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
251
|
+
expect(await sqlite3.column_name(stmt, 0)).toEqual('column1');
|
|
252
|
+
expect(await sqlite3.column_name(stmt, 1)).toEqual('column2');
|
|
253
|
+
expect(await sqlite3.column_name(stmt, 2)).toEqual('column3');
|
|
254
|
+
expect(await sqlite3.column_name(stmt, 3)).toEqual('column4');
|
|
255
|
+
expect(await sqlite3.column_name(stmt, 4)).toEqual('column5');
|
|
256
|
+
|
|
257
|
+
expect(await sqlite3.column_names(stmt))
|
|
258
|
+
.toEqual(['column1', 'column2', 'column3', 'column4', 'column5']);
|
|
259
|
+
|
|
260
|
+
rc = await sqlite3.bind_collection(stmt, [
|
|
261
|
+
cBlob,
|
|
262
|
+
cDouble,
|
|
263
|
+
cInt,
|
|
264
|
+
cNull,
|
|
265
|
+
cText,
|
|
266
|
+
]);
|
|
267
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
268
|
+
|
|
269
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
270
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
271
|
+
expect(await sqlite3.data_count(stmt)).toEqual(5)
|
|
272
|
+
expect(await sqlite3.column_count(stmt)).toEqual(5);
|
|
273
|
+
|
|
274
|
+
const row = await sqlite3.row(stmt);
|
|
275
|
+
expect(row.length).toEqual(5);
|
|
276
|
+
|
|
277
|
+
expect(row[0] instanceof Uint8Array).toBeTrue();
|
|
278
|
+
expect([...row[0]]).toEqual([...cBlob]);
|
|
279
|
+
expect(row[1]).toEqual(cDouble);
|
|
280
|
+
expect(row[2]).toEqual(cInt);
|
|
281
|
+
expect(row[3]).toEqual(cNull);
|
|
282
|
+
expect(row[4]).toEqual(cText);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should bind collection object', async function() {
|
|
288
|
+
let rc;
|
|
289
|
+
const sql = 'VALUES (:cBlob, :cDouble, :cInt, :cNull, :cText)';
|
|
290
|
+
const cBlob = new Uint8Array([8, 6, 7, 5, 3, 0, 9]);
|
|
291
|
+
const cDouble = Math.PI;
|
|
292
|
+
const cInt = 42;
|
|
293
|
+
const cNull = null;
|
|
294
|
+
const cText = 'foobar';
|
|
295
|
+
|
|
296
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
297
|
+
expect(await sqlite3.bind_parameter_count(stmt)).toEqual(5);
|
|
298
|
+
expect(await sqlite3.bind_parameter_name(stmt, 1)).toEqual(':cBlob');
|
|
299
|
+
expect(await sqlite3.bind_parameter_name(stmt, 2)).toEqual(':cDouble');
|
|
300
|
+
expect(await sqlite3.bind_parameter_name(stmt, 3)).toEqual(':cInt');
|
|
301
|
+
expect(await sqlite3.bind_parameter_name(stmt, 4)).toEqual(':cNull');
|
|
302
|
+
expect(await sqlite3.bind_parameter_name(stmt, 5)).toEqual(':cText');
|
|
303
|
+
|
|
304
|
+
rc = await sqlite3.bind_collection(stmt, {
|
|
305
|
+
':cBlob': cBlob,
|
|
306
|
+
':cDouble': cDouble,
|
|
307
|
+
':cInt': cInt,
|
|
308
|
+
':cNull': cNull,
|
|
309
|
+
':cText': cText
|
|
310
|
+
});
|
|
311
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
312
|
+
|
|
313
|
+
while ((rc = await sqlite3.step(stmt)) !== SQLite.SQLITE_DONE) {
|
|
314
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
315
|
+
|
|
316
|
+
expect(await sqlite3.column_count(stmt)).toEqual(5);
|
|
317
|
+
const row = await sqlite3.row(stmt);
|
|
318
|
+
expect(row.length).toEqual(5);
|
|
319
|
+
|
|
320
|
+
expect(row[0] instanceof Uint8Array).toBeTrue();
|
|
321
|
+
expect([...row[0]]).toEqual([...cBlob]);
|
|
322
|
+
expect(row[1]).toEqual(cDouble);
|
|
323
|
+
expect(row[2]).toEqual(cInt);
|
|
324
|
+
expect(row[3]).toEqual(cNull);
|
|
325
|
+
expect(row[4]).toEqual(cText);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('should allow unscoped lifetime', async function() {
|
|
331
|
+
let rc;
|
|
332
|
+
|
|
333
|
+
rc = await sqlite3.exec(db, `
|
|
334
|
+
CREATE TABLE t AS VALUES ('foo', 0), ('bar', 1), ('baz', 2);
|
|
335
|
+
`);
|
|
336
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
337
|
+
|
|
338
|
+
let stmt;
|
|
339
|
+
const sql = 'SELECT column2 FROM t WHERE column1 = ?';
|
|
340
|
+
for await (const s of i(sqlite3.statements(db, sql, { unscoped: true }))) {
|
|
341
|
+
if (s) {
|
|
342
|
+
stmt = s;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
expect(stmt).toBeGreaterThan(0);
|
|
346
|
+
|
|
347
|
+
// The statement should be active beyond the iterator lifecycle.
|
|
348
|
+
rc = await sqlite3.bind_text(stmt, 1, 'foo');
|
|
349
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
350
|
+
rc = await sqlite3.step(stmt);
|
|
351
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
352
|
+
await expectAsync(sqlite3.column_int(stmt, 0)).toBeResolvedTo(0);
|
|
353
|
+
|
|
354
|
+
rc = await sqlite3.reset(stmt);
|
|
355
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
356
|
+
|
|
357
|
+
rc = await sqlite3.bind_text(stmt, 1, 'bar');
|
|
358
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
359
|
+
rc = await sqlite3.step(stmt);
|
|
360
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
361
|
+
await expectAsync(sqlite3.column_int(stmt, 0)).toBeResolvedTo(1);
|
|
362
|
+
|
|
363
|
+
rc = await sqlite3.step(stmt);
|
|
364
|
+
expect(rc).toEqual(SQLite.SQLITE_DONE);
|
|
365
|
+
|
|
366
|
+
rc = await sqlite3.finalize(stmt);
|
|
367
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('should clear bindings', async function() {
|
|
371
|
+
let rc;
|
|
372
|
+
|
|
373
|
+
const sql = 'SELECT ?';
|
|
374
|
+
for await (const stmt of i(sqlite3.statements(db, sql))) {
|
|
375
|
+
{
|
|
376
|
+
rc = await sqlite3.bind_int(stmt, 1, 42);
|
|
377
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
378
|
+
|
|
379
|
+
rc = await sqlite3.reset(stmt);
|
|
380
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
381
|
+
|
|
382
|
+
rc = await sqlite3.step(stmt);
|
|
383
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
384
|
+
|
|
385
|
+
const value = await sqlite3.column(stmt, 0);
|
|
386
|
+
expect(value).toEqual(42);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
{
|
|
390
|
+
rc = await sqlite3.clear_bindings(stmt);
|
|
391
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
392
|
+
|
|
393
|
+
rc = await sqlite3.reset(stmt);
|
|
394
|
+
expect(rc).toEqual(SQLite.SQLITE_OK);
|
|
395
|
+
|
|
396
|
+
rc = await sqlite3.step(stmt);
|
|
397
|
+
expect(rc).toEqual(SQLite.SQLITE_ROW);
|
|
398
|
+
|
|
399
|
+
const value = await sqlite3.column(stmt, 0);
|
|
400
|
+
expect(value).not.toEqual(42);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// sqlite3.statements() returns an async iterator, but its Comlink
|
|
408
|
+
// proxy needs this wrapper to be used.
|
|
409
|
+
async function* i(p) {
|
|
410
|
+
const x = await p;
|
|
411
|
+
try {
|
|
412
|
+
let value, done;
|
|
413
|
+
while (true) {
|
|
414
|
+
({ value, done } = await x.next());
|
|
415
|
+
if (!done) {
|
|
416
|
+
yield value;
|
|
417
|
+
} else {
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
} catch (e) {
|
|
422
|
+
await x.throw(e);
|
|
423
|
+
} finally {
|
|
424
|
+
await x.return();
|
|
425
|
+
}
|
|
426
|
+
}
|