|
14 | 14 | import { setAppContext } from '$lib/context';
|
15 | 15 | import { FileDropEventManager } from '$lib/FileDropEventManager';
|
16 | 16 | import Bars3 from '$lib/icons/Bars3.svelte';
|
| 17 | + import Bold from '$lib/icons/Bold.svelte'; |
17 | 18 | import Copy from '$lib/icons/Copy.svelte';
|
18 | 19 | import MagicWand from '$lib/icons/MagicWand.svelte';
|
19 | 20 | import PanelBottom from '$lib/icons/PanelBottom.svelte';
|
|
27 | 28 | import { historyRepository, type HistoryEntry } from '$lib/repositories/history';
|
28 | 29 | import { queryRepository, type Query } from '$lib/repositories/queries';
|
29 | 30 | import { tabRepository, type Tab } from '$lib/repositories/tabs';
|
| 31 | + import { IndexedDBCache } from '@agnosticeng/cache'; |
30 | 32 | import { SplitPane } from '@rich_harris/svelte-split-pane';
|
31 | 33 | import debounce from 'p-debounce';
|
32 | 34 | import { format } from 'sql-formatter';
|
|
36 | 38 | let loading = $state(false);
|
37 | 39 | let counter = $state<ReturnType<typeof TimeCounter>>();
|
38 | 40 |
|
39 |
| - async function handleExec() { |
| 41 | + const cache = new IndexedDBCache({ dbName: 'query-cache', storeName: 'response-data' }); |
| 42 | + let cached = $state(false); |
| 43 | +
|
| 44 | + async function handleExec(force = false) { |
40 | 45 | const query = currentTab.content;
|
41 | 46 | if (loading || !query) return;
|
42 | 47 |
|
43 | 48 | loading = true;
|
44 | 49 | counter?.start();
|
45 | 50 | try {
|
| 51 | + if (!force) { |
| 52 | + const r = await cache.get(query); |
| 53 | + if (r) { |
| 54 | + cached = true; |
| 55 | + response = r; |
| 56 | + cached = true; |
| 57 | + bottomPanel.open = true; |
| 58 | + if (bottomPanelTab === 'logs') bottomPanelTab = 'data'; |
| 59 | + return; |
| 60 | + } |
| 61 | + } |
| 62 | +
|
46 | 63 | response = await engine.exec(query);
|
| 64 | + cached = false; |
| 65 | + await cache.set(query, response); |
47 | 66 | } finally {
|
48 | 67 | loading = false;
|
49 | 68 | counter?.stop();
|
@@ -390,9 +409,22 @@ LIMIT 100;`;
|
390 | 409 | <button class="action" title="Save" onclick={handleSaveQuery} disabled={!canSave}>
|
391 | 410 | <Save size="12" />
|
392 | 411 | </button>
|
393 |
| - <button class="action" title="Run" onclick={handleExec} disabled={loading}> |
| 412 | + <button |
| 413 | + class="action" |
| 414 | + title="Run" |
| 415 | + onclick={() => handleExec()} |
| 416 | + disabled={loading} |
| 417 | + > |
394 | 418 | <Play size="12" />
|
395 | 419 | </button>
|
| 420 | + <button |
| 421 | + class="action" |
| 422 | + title="Force run" |
| 423 | + onclick={() => handleExec(true)} |
| 424 | + disabled={loading} |
| 425 | + > |
| 426 | + <Bold size="12" /> |
| 427 | + </button> |
396 | 428 | </div>
|
397 | 429 | </nav>
|
398 | 430 | {#each tabs as tab, i (tab.id)}
|
@@ -424,6 +456,9 @@ LIMIT 100;`;
|
424 | 456 | <PanelLeft size="12" />
|
425 | 457 | </button>
|
426 | 458 | <div class="spacer"></div>
|
| 459 | + {#if cached} |
| 460 | + <span>from cache</span> |
| 461 | + {/if} |
427 | 462 | <TimeCounter bind:this={counter} />
|
428 | 463 | {#if BUILD}
|
429 | 464 | <span class="label">build-{BUILD}</span>
|
|
0 commit comments