Skip to content

Commit 85ec97d

Browse files
committed
Cache queries
1 parent d55fad3 commit 85ec97d

2 files changed

Lines changed: 39 additions & 22 deletions

File tree

index.js

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,54 @@ import { atom, onMount } from 'nanostores'
33
function parseQuery(query, params) {
44
if ('toSQL' in query) {
55
let q = query.toSQL()
6-
return [q.sql, q.params]
6+
let full = q.sql + JSON.stringify(q.params)
7+
return [q.sql, q.params, full]
78
}
89
let sql = query[0]
10+
let full = query[0]
911
for (let i = 0; i < params.length; i++) {
1012
sql += '?' + query[i + 1]
13+
full += JSON.stringify(params[i]) + query[i + 1]
1114
}
12-
return [sql, params]
15+
return [sql, params, full]
1316
}
1417

1518
export function openDb(rootDriver) {
19+
let cache = new Map()
20+
1621
function createDb(driver) {
1722
let db = {
1823
opened: true,
1924
driver,
2025

2126
store(query, ...rest) {
22-
let [sql, params] = parseQuery(query, rest)
23-
let $store = atom({ isLoading: true })
24-
if (!db.opened) return $store
25-
let currentJSON
26-
let subscribed = false
27-
onMount($store, () => {
28-
subscribed = true
29-
let unbind = driver.subscribe(sql, params, rows => {
30-
if (!subscribed) return
31-
let prevJSON = currentJSON
32-
currentJSON = JSON.stringify(rows)
33-
if (!$store.value || prevJSON !== currentJSON) {
34-
$store.set({ isLoading: false, value: rows })
27+
let [sql, params, cacheKey] = parseQuery(query, rest)
28+
if (cache.has(cacheKey)) {
29+
return cache.get(cacheKey)
30+
} else {
31+
let $store = atom({ isLoading: true })
32+
if (!db.opened) return $store
33+
let currentJSON
34+
let subscribed = false
35+
onMount($store, () => {
36+
subscribed = true
37+
let unbind = driver.subscribe(sql, params, rows => {
38+
if (!subscribed) return
39+
let prevJSON = currentJSON
40+
currentJSON = JSON.stringify(rows)
41+
if (!$store.value || prevJSON !== currentJSON) {
42+
$store.set({ isLoading: false, value: rows })
43+
}
44+
})
45+
return () => {
46+
cache.delete(cacheKey)
47+
subscribed = false
48+
unbind()
3549
}
3650
})
37-
return () => {
38-
subscribed = false
39-
unbind()
40-
}
41-
})
42-
return $store
51+
cache.set(cacheKey, $store)
52+
return $store
53+
}
4354
},
4455

4556
exec(query, ...rest) {

test/db.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { eq } from 'drizzle-orm'
22
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
33
import { drizzle } from 'drizzle-orm/sqlite-proxy'
44
import { STORE_UNMOUNT_DELAY } from 'nanostores'
5-
import { deepEqual, equal, match } from 'node:assert/strict'
5+
import { deepEqual, equal, match, notEqual } from 'node:assert/strict'
66
import { afterEach, describe, test } from 'node:test'
77
import { setTimeout } from 'node:timers/promises'
88

@@ -96,6 +96,9 @@ for (let [driverName, setup] of Object.entries(DRIVERS)) {
9696
]
9797
}
9898
])
99+
100+
let $other = db.store<Item>`SELECT * FROM items ORDER BY id`
101+
equal($other, $items)
99102
})
100103

101104
test('transaction commits', async () => {
@@ -236,6 +239,9 @@ for (let [driverName, setup] of Object.entries(DRIVERS)) {
236239
isLoading: false,
237240
value: [{ id: 1, title: 'first' }]
238241
})
242+
243+
let $other = db.store<Item>`SELECT * FROM items ORDER BY id`
244+
notEqual($other, $items)
239245
})
240246

241247
test('supports Drizzle in store', async () => {

0 commit comments

Comments
 (0)