Skip to content

Commit 3e65580

Browse files
committed
feat: add query function , fix iterator function
1 parent 50ac6b6 commit 3e65580

1 file changed

Lines changed: 65 additions & 20 deletions

File tree

src/utils.ts

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
SQLITE_DETERMINISTIC,
33
SQLITE_DIRECTONLY,
4-
SQLITE_OK,
4+
SQLITE_DONE,
55
SQLITE_OPEN_CREATE,
66
SQLITE_OPEN_READONLY,
77
SQLITE_OPEN_READWRITE,
@@ -262,43 +262,88 @@ export async function run(
262262
return results
263263
}
264264

265+
function createRowMapper(sqlite: SQLiteDBCore['sqlite'], stmt: number) {
266+
const cols = sqlite.column_names(stmt)
267+
return (row: any[]) => Object.fromEntries(cols.map((key, i) => [key, row[i]]))
268+
}
269+
270+
export async function query(
271+
core: SQLiteDBCore,
272+
sql: string,
273+
parameters?: SQLiteCompatibleType[],
274+
): Promise<Record<string, SQLiteCompatibleType>[]> {
275+
const iterator = core.sqlite.statements(core.pointer, sql)[Symbol.asyncIterator]()
276+
const { value: stmt } = await iterator.next()
277+
278+
try {
279+
if (parameters?.length) {
280+
core.sqlite.bind_collection(stmt, parameters)
281+
}
282+
283+
const size = core.sqlite.column_count(stmt)
284+
if (size === 0) {
285+
await core.sqlite.step(stmt)
286+
return []
287+
}
288+
289+
const mapRow = createRowMapper(core.sqlite, stmt)
290+
const result = []
291+
let idx = 0
292+
while ((await core.sqlite.step(stmt)) === SQLITE_ROW) {
293+
result[idx++] = mapRow(core.sqlite.row(stmt))
294+
}
295+
return result
296+
} finally {
297+
await iterator.return?.()
298+
}
299+
}
300+
265301
export async function* iterator(
266302
core: SQLiteDBCore,
267303
sql: string,
268304
parameters?: SQLiteCompatibleType[],
269305
chunkSize = 1,
270-
): AsyncIterableIterator<Record<string, SQLiteCompatibleType>[]> {
306+
): AsyncIterableIterator<Record<string, SQLiteCompatibleType>> {
271307
const { sqlite, pointer } = core
272-
// eslint-disable-next-line unicorn/no-new-array
273-
let cache = new Array(chunkSize)
308+
const cache = new Array(chunkSize)
274309
for await (const stmt of sqlite.statements(pointer, sql)) {
275310
if (parameters?.length) {
276311
sqlite.bind_collection(stmt, parameters)
277312
}
278313
let idx = 0
279-
const cols = sqlite.column_names(stmt)
314+
const mapRow = createRowMapper(core.sqlite, stmt)
315+
280316
while (1) {
281-
const result = await sqlite.step(stmt)
282-
if (result === SQLITE_ROW) {
283-
const row = sqlite.row(stmt)
284-
cache[idx] = Object.fromEntries(cols.map((key, i) => [key, row[i]]))
285-
if (++idx === chunkSize) {
286-
yield cache.slice(0, idx)
287-
idx = 0
288-
}
289-
} else if (result === SQLITE_OK) {
290-
if (++idx === chunkSize) {
291-
yield []
317+
try {
318+
const result = await sqlite.step(stmt)
319+
320+
if (result === SQLITE_ROW) {
321+
cache[idx] = mapRow(core.sqlite.row(stmt))
322+
323+
if (++idx === chunkSize) {
324+
for (let i = 0; i < idx; i++) {
325+
yield cache[i]
326+
}
327+
idx = 0
328+
}
329+
} else if (result === SQLITE_DONE) {
330+
if (idx > 0) {
331+
for (let i = 0; i < idx; i++) {
332+
yield cache[i]
333+
}
334+
idx = 0
335+
}
336+
break
292337
}
293-
} else {
338+
} finally {
294339
if (idx > 0) {
295-
yield cache.slice(0, idx)
340+
for (let i = 0; i < idx; i++) {
341+
yield cache[i]
342+
}
296343
}
297-
break
298344
}
299345
}
300346
}
301-
cache = undefined!
302347
}
303348

304349
export function parseOpenV2Flag(readonly?: boolean): number {

0 commit comments

Comments
 (0)