Skip to content

Commit c43a06e

Browse files
committed
Support both a pool and direct client.
1 parent c22d6c5 commit c43a06e

File tree

5 files changed

+110
-10
lines changed

5 files changed

+110
-10
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
node_modules/
22
test-db/
33
*.db
4+
*.db-wal
5+
*.db-shm
46
lib/
57
tsconfig.tsbuildinfo
68
benchmarks/db
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { BetterSqliteDriver } from '@sqlite-js/better-sqlite3-driver';
2-
import { SqliteClientPool, SqliteClientOptions } from './core.js';
2+
import { SqliteClientPool, SqliteClientOptions, SqliteClient } from './core.js';
33
import { fileURLToPath } from 'node:url';
44

5-
export class BetterSqliteClient extends SqliteClientPool {
5+
export class BetterSqliteClient extends SqliteClient {
66
constructor(connectionUrl: string | URL, options: SqliteClientOptions = {}) {
77
if (typeof connectionUrl != 'string') {
88
connectionUrl = fileURLToPath(connectionUrl);
@@ -11,3 +11,13 @@ export class BetterSqliteClient extends SqliteClientPool {
1111
super(connectionUrl, pool, options);
1212
}
1313
}
14+
15+
export class BetterSqliteClientPool extends SqliteClientPool {
16+
constructor(connectionUrl: string | URL, options: SqliteClientOptions = {}) {
17+
if (typeof connectionUrl != 'string') {
18+
connectionUrl = fileURLToPath(connectionUrl);
19+
}
20+
const pool = BetterSqliteDriver.open(connectionUrl);
21+
super(connectionUrl, pool, options);
22+
}
23+
}

packages/stdext-sql-adapter/src/connection.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export class SqliteConnection
2727
SqliteQueryOptions
2828
>
2929
{
30-
public driver: SqliteDriverConnection;
30+
public driver: SqliteDriverConnection | undefined;
31+
3132
public readonly connectionUrl: string;
3233

3334
get connected(): boolean {
@@ -38,7 +39,7 @@ export class SqliteConnection
3839

3940
constructor(
4041
connectionUrl: string,
41-
driver: SqliteDriverConnection,
42+
driver: SqliteDriverConnection | undefined,
4243
options?: SqliteConnectionOptions
4344
) {
4445
this.connectionUrl = connectionUrl;
@@ -47,11 +48,11 @@ export class SqliteConnection
4748
}
4849

4950
async connect(): Promise<void> {
50-
// We're always connected
51+
// No-op
5152
}
5253

5354
async close(): Promise<void> {
54-
await this.driver.close();
55+
await this.driver?.close();
5556
}
5657

5758
async execute(
@@ -127,6 +128,29 @@ export class SqliteConnection
127128
}
128129
}
129130

131+
export class SqliteReservedConnection extends SqliteConnection {
132+
#connect: () => Promise<ReservedConnection>;
133+
#reserved: ReservedConnection | undefined;
134+
135+
constructor(
136+
connectionUrl: string,
137+
connect: () => Promise<ReservedConnection>,
138+
options?: SqliteConnectionOptions
139+
) {
140+
super(connectionUrl, undefined, options);
141+
this.#connect = connect;
142+
}
143+
144+
async connect(): Promise<void> {
145+
this.#reserved = await this.#connect();
146+
this.driver = this.#reserved.connection;
147+
}
148+
149+
async close(): Promise<void> {
150+
await this.#reserved?.release();
151+
}
152+
}
153+
130154
export class SqliteConnectable
131155
implements SqlConnectable<SqliteConnectionOptions, SqliteConnection>
132156
{

packages/stdext-sql-adapter/src/core.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
import {
2626
SqliteConnectable,
2727
SqliteConnection,
28+
SqliteReservedConnection,
2829
type SqliteConnectionOptions
2930
} from './connection.js';
3031
import { SqliteTransactionError } from './errors.js';
@@ -442,6 +443,57 @@ export class SqliteTransactionable
442443
}
443444
}
444445

446+
/**
447+
* Single-connection client. Not safe to use concurrently.
448+
*/
449+
export class SqliteClient
450+
extends SqliteTransactionable
451+
implements
452+
SqlClient<
453+
SqliteEventTarget,
454+
SqliteConnectionOptions,
455+
SqliteParameterType,
456+
SqliteQueryOptions,
457+
SqliteConnection,
458+
SqlitePreparedStatement,
459+
SqliteTransactionOptions,
460+
SqliteTransaction
461+
>
462+
{
463+
readonly eventTarget: SqliteEventTarget;
464+
465+
constructor(
466+
connectionUrl: string,
467+
pool: SqliteDriverConnectionPool,
468+
options: SqliteClientOptions = {}
469+
) {
470+
const connect = () => {
471+
return pool.reserveConnection();
472+
};
473+
const conn = new SqliteReservedConnection(connectionUrl, connect, options);
474+
super(conn, options);
475+
this.eventTarget = new SqliteEventTarget();
476+
}
477+
478+
async connect(): Promise<void> {
479+
await this.connection.connect();
480+
this.eventTarget.dispatchEvent(
481+
new SqliteConnectEvent({ connection: this.connection } as any)
482+
);
483+
}
484+
485+
async close(): Promise<void> {
486+
this.eventTarget.dispatchEvent(
487+
new SqliteCloseEvent({ connection: this.connection } as any)
488+
);
489+
await this.connection.close();
490+
}
491+
492+
async [Symbol.asyncDispose](): Promise<void> {
493+
await this.close();
494+
}
495+
}
496+
445497
class SqlitePoolClient
446498
extends SqliteTransactionable
447499
implements

packages/stdext-sql-adapter/test/src/adapter.test.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
import * as fs from 'node:fs/promises';
22
import { fileURLToPath } from 'node:url';
33
import { assert, test } from 'vitest';
4-
import { BetterSqliteClient, SqliteClientPool } from '../../lib/index.js';
4+
import {
5+
BetterSqliteClient,
6+
BetterSqliteClientPool,
7+
SqliteClient,
8+
SqliteClientPool
9+
} from '../../lib/index.js';
510

611
const assertEquals = assert.deepEqual;
712

813
test('sqlite', async () => {
9-
const DB_URL = new URL('./test.db', import.meta.url);
14+
const DB_URL = new URL('../../test.db', import.meta.url);
1015
const path = fileURLToPath(DB_URL);
1116

1217
// Remove any existing test.db.
1318
await fs.rm(path).catch(() => {});
19+
await fs.rm(path + '-shm').catch(() => {});
20+
await fs.rm(path + '-wal').catch(() => {});
21+
22+
// To test the pool:
23+
// let pool: SqliteClientPool = new BetterSqliteClientPool(path);
24+
// let db = await pool.acquire();
25+
26+
let db: SqliteClient = new BetterSqliteClient(path);
27+
await db.connect();
1428

15-
let pool: SqliteClientPool = new BetterSqliteClient(path);
16-
let db = await pool.acquire();
1729
await db.execute('pragma journal_mode = WAL');
1830
await db.execute('pragma synchronous = normal');
1931
assertEquals(await db.execute('pragma temp_store = memory'), 0);

0 commit comments

Comments
 (0)