Fixes #97: SQLite is now async, optimized, tests

This commit is contained in:
Zef Hemel
2022-10-21 10:00:43 +02:00
parent b9da9b7965
commit c1a78e0105
65 changed files with 329 additions and 142 deletions
+11 -16
View File
@@ -1,48 +1,43 @@
import { SQLite } from "../../server/deps.ts";
import { AsyncSQLite } from "../../plugos/sqlite/async_sqlite.ts";
import { SysCallMapping } from "../system.ts";
import { asyncExecute, asyncQuery } from "./store.deno.ts";
export function ensureFTSTable(
db: SQLite,
export async function ensureFTSTable(
db: AsyncSQLite,
tableName: string,
) {
const result = db.query(
const result = await db.query(
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
[tableName],
tableName,
);
if (result.length === 0) {
asyncExecute(
db,
await db.execute(
`CREATE VIRTUAL TABLE ${tableName} USING fts5(key, value);`,
);
console.log(`Created fts5 table ${tableName}`);
}
return Promise.resolve();
}
export function fullTextSearchSyscalls(
db: SQLite,
db: AsyncSQLite,
tableName: string,
): SysCallMapping {
return {
"fulltext.index": async (_ctx, key: string, value: string) => {
await asyncExecute(db, `DELETE FROM ${tableName} WHERE key = ?`, key);
await asyncExecute(
db,
await db.execute(`DELETE FROM ${tableName} WHERE key = ?`, key);
await db.execute(
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)`,
key,
value,
);
},
"fulltext.delete": async (_ctx, key: string) => {
await asyncExecute(db, `DELETE FROM ${tableName} WHERE key = ?`, key);
await db.execute(`DELETE FROM ${tableName} WHERE key = ?`, key);
},
"fulltext.search": async (_ctx, phrase: string, limit: number) => {
console.log("Got search query", phrase);
return (
await asyncQuery<any>(
db,
await db.query(
`SELECT key, rank FROM ${tableName} WHERE value MATCH ? ORDER BY key, rank LIMIT ?`,
phrase,
limit,
+5 -3
View File
@@ -1,11 +1,12 @@
import { assertEquals } from "../../test_deps.ts";
import { SQLite } from "../../server/deps.ts";
import { createSandbox } from "../environments/deno_sandbox.ts";
import { System } from "../system.ts";
import { ensureTable, storeSyscalls } from "./store.deno.ts";
import { AsyncSQLite } from "../sqlite/async_sqlite.ts";
Deno.test("Test store", async () => {
const db = new SQLite(":memory:");
const db = new AsyncSQLite(":memory:");
await db.init();
await ensureTable(db, "test_table");
const system = new System("server");
const syscalls = storeSyscalls(db, "test_table");
@@ -100,7 +101,8 @@ Deno.test("Test store", async () => {
});
allRoberts = await syscalls["store.query"](dummyCtx, {});
// console.log("All Roberts", allRoberts);
assertEquals(allRoberts.length, 2);
db.close();
db.stop();
});
+34 -53
View File
@@ -1,4 +1,4 @@
import { SQLite } from "../../server/deps.ts";
import { AsyncSQLite } from "../sqlite/async_sqlite.ts";
import { SysCallMapping } from "../system.ts";
export type Item = {
@@ -12,18 +12,17 @@ export type KV = {
value: any;
};
export function ensureTable(db: SQLite, tableName: string) {
const result = db.query(
export async function ensureTable(db: AsyncSQLite, tableName: string) {
const result = await db.query(
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
[tableName],
tableName,
);
if (result.length === 0) {
db.execute(
await db.execute(
`CREATE TABLE ${tableName} (key STRING PRIMARY KEY, value TEXT);`,
);
console.log(`Created table ${tableName}`);
}
return Promise.resolve();
}
export type Query = {
@@ -72,68 +71,53 @@ export function queryToSql(
};
}
export function asyncQuery<T extends Record<string, unknown>>(
db: SQLite,
query: string,
...params: any[]
): Promise<T[]> {
// console.log("Querying", query, params);
return Promise.resolve(db.queryEntries(query, params));
}
export function asyncExecute(
db: SQLite,
query: string,
...params: any[]
): Promise<number> {
// console.log("Exdecting", query, params);
db.query(query, params);
return Promise.resolve(db.changes);
}
export function storeSyscalls(
db: SQLite,
db: AsyncSQLite,
tableName: string,
): SysCallMapping {
const apiObj: SysCallMapping = {
"store.delete": async (_ctx, key: string) => {
await asyncExecute(db, `DELETE FROM ${tableName} WHERE key = ?`, key);
await db.execute(`DELETE FROM ${tableName} WHERE key = ?`, key);
},
"store.deletePrefix": async (_ctx, prefix: string) => {
await asyncExecute(
db,
await db.execute(
`DELETE FROM ${tableName} WHERE key LIKE ?`,
`${prefix}%`,
);
},
"store.deleteQuery": async (_ctx, query: Query) => {
const { sql, params } = queryToSql(query);
await asyncExecute(db, `DELETE FROM ${tableName} ${sql}`, ...params);
await db.execute(`DELETE FROM ${tableName} ${sql}`, ...params);
},
"store.deleteAll": async () => {
await asyncExecute(db, `DELETE FROM ${tableName}`);
await db.execute(`DELETE FROM ${tableName}`);
},
"store.set": async (_ctx, key: string, value: any) => {
await asyncExecute(
db,
`UPDATE ${tableName} SET value = ? WHERE key = ?`,
JSON.stringify(value),
await db.execute(
`INSERT INTO ${tableName}
(key, value)
VALUES (?, ?)
ON CONFLICT(key)
DO UPDATE SET value=excluded.value`,
key,
JSON.stringify(value),
);
if (db.changes === 0) {
await asyncExecute(
db,
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)`,
key,
JSON.stringify(value),
);
}
},
// TODO: Optimize
"store.batchSet": async (ctx, kvs: KV[]) => {
for (const { key, value } of kvs) {
await apiObj["store.set"](ctx, key, value);
"store.batchSet": async (_ctx, kvs: KV[]) => {
if (kvs.length === 0) {
return;
}
const values = kvs.flatMap((
kv,
) => [kv.key, JSON.stringify(kv.value)]);
await db.execute(
`INSERT INTO ${tableName}
(key, value)
VALUES ${kvs.map((_) => "(?, ?)").join(",")}
ON CONFLICT(key)
DO UPDATE SET value=excluded.value`,
...values,
);
},
"store.batchDelete": async (ctx, keys: string[]) => {
for (const key of keys) {
@@ -141,8 +125,7 @@ export function storeSyscalls(
}
},
"store.get": async (_ctx, key: string): Promise<any | null> => {
const result = await asyncQuery<Item>(
db,
const result = await db.query(
`SELECT value FROM ${tableName} WHERE key = ?`,
key,
);
@@ -154,8 +137,7 @@ export function storeSyscalls(
},
"store.queryPrefix": async (_ctx, prefix: string) => {
return (
await asyncQuery<Item>(
db,
await db.query(
`SELECT key, value FROM ${tableName} WHERE key LIKE ?`,
`${prefix}%`,
)
@@ -167,8 +149,7 @@ export function storeSyscalls(
"store.query": async (_ctx, query: Query) => {
const { sql, params } = queryToSql(query);
return (
await asyncQuery<Item>(
db,
await db.query(
`SELECT key, value FROM ${tableName} ${sql}`,
...params,
)