

























11import { DatabaseSync } from "node:sqlite";
2-import { Kysely, sql, type Generated } from "kysely";
3-import { afterEach, describe, expect, it } from "vitest";
2+import { CompiledQuery, Kysely, sql, type Generated } from "kysely";
3+import { afterEach, describe, expect, it, vi } from "vitest";
44import { NodeSqliteKyselyDialect } from "./kysely-node-sqlite.js";
5566type TestDatabase = {
@@ -19,19 +19,7 @@ describe("NodeSqliteKyselyDialect", () => {
1919});
20202121it("uses node:sqlite with raw row-returning queries and returning clauses", async () => {
22-db = new Kysely<TestDatabase>({
23-dialect: new NodeSqliteKyselyDialect({
24-database: new DatabaseSync(":memory:"),
25-}),
26-});
27-28-await db.schema
29-.createTable("person")
30-.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
31-.addColumn("name", "text", (col) => col.notNull())
32-.execute();
33-34-await db.insertInto("person").values({ name: "Ada" }).execute();
22+db = await createTestDb();
35233624await expect(db.selectFrom("person").selectAll().execute()).resolves.toEqual([
3725{ id: 1, name: "Ada" },
@@ -60,4 +48,124 @@ describe("NodeSqliteKyselyDialect", () => {
6048expect(update.insertId).toBeUndefined();
6149expect(update.numAffectedRows).toBe(1n);
6250});
51+52+it("creates the database lazily and runs the connection hook once", async () => {
53+const sqlite = new DatabaseSync(":memory:");
54+const createDatabase = vi.fn(() => sqlite);
55+const onCreateConnection = vi.fn(async (connection) => {
56+await connection.executeQuery(CompiledQuery.raw("pragma user_version = 7"));
57+});
58+59+db = new Kysely<TestDatabase>({
60+dialect: new NodeSqliteKyselyDialect({
61+database: createDatabase,
62+ onCreateConnection,
63+}),
64+});
65+66+await expect(
67+sql<{ user_version: number }>`pragma user_version`.execute(db),
68+).resolves.toMatchObject({
69+rows: [{ user_version: 7 }],
70+});
71+expect(createDatabase).toHaveBeenCalledTimes(1);
72+expect(onCreateConnection).toHaveBeenCalledTimes(1);
73+});
74+75+it("returns insert metadata only for changed insert statements", async () => {
76+db = new Kysely<TestDatabase>({
77+dialect: new NodeSqliteKyselyDialect({
78+database: new DatabaseSync(":memory:"),
79+}),
80+});
81+await createPersonTable(db);
82+83+const insertResult = await db
84+.insertInto("person")
85+.values({ name: "Ada" })
86+.executeTakeFirstOrThrow();
87+expect(insertResult.insertId).toBe(1n);
88+expect(insertResult.numInsertedOrUpdatedRows).toBe(1n);
89+90+const updateResult = await db
91+.updateTable("person")
92+.set({ name: "Ada Lovelace" })
93+.where("id", "=", 1)
94+.executeTakeFirstOrThrow();
95+expect(updateResult.numUpdatedRows).toBe(1n);
96+97+const ignoredInsert = await sql`
98+ insert or ignore into person (id, name) values (${1}, ${"Ada Again"})
99+ `.execute(db);
100+expect(ignoredInsert.insertId).toBeUndefined();
101+expect(ignoredInsert.numAffectedRows).toBe(0n);
102+});
103+104+it("rolls back transactions and controlled savepoints", async () => {
105+db = new Kysely<TestDatabase>({
106+dialect: new NodeSqliteKyselyDialect({
107+database: new DatabaseSync(":memory:"),
108+}),
109+});
110+await createPersonTable(db);
111+112+await expect(
113+db.transaction().execute(async (trx) => {
114+await trx.insertInto("person").values({ name: "Rollback" }).execute();
115+throw new Error("rollback outer");
116+}),
117+).rejects.toThrow("rollback outer");
118+await expect(db.selectFrom("person").selectAll().execute()).resolves.toEqual([]);
119+120+const trx = await db.startTransaction().execute();
121+await trx.insertInto("person").values({ name: "Ada" }).execute();
122+const afterAda = await trx.savepoint("after_ada").execute();
123+await afterAda.insertInto("person").values({ name: "Grace" }).execute();
124+const afterRollback = await afterAda.rollbackToSavepoint("after_ada").execute();
125+await afterRollback.insertInto("person").values({ name: "Lin" }).execute();
126+await afterRollback.commit().execute();
127+128+await expect(db.selectFrom("person").select("name").orderBy("id").execute()).resolves.toEqual([
129+{ name: "Ada" },
130+{ name: "Lin" },
131+]);
132+});
133+134+it("streams selected rows through node:sqlite iteration", async () => {
135+db = await createTestDb();
136+await db
137+.insertInto("person")
138+.values([{ name: "Grace" }, { name: "Lin" }])
139+.execute();
140+141+const rows: Array<{ id: number; name: string }> = [];
142+for await (const row of db.selectFrom("person").selectAll().orderBy("id").stream(1)) {
143+rows.push(row);
144+}
145+146+expect(rows).toEqual([
147+{ id: 1, name: "Ada" },
148+{ id: 2, name: "Grace" },
149+{ id: 3, name: "Lin" },
150+]);
151+});
63152});
153+154+async function createTestDb(): Promise<Kysely<TestDatabase>> {
155+const testDb = new Kysely<TestDatabase>({
156+dialect: new NodeSqliteKyselyDialect({
157+database: new DatabaseSync(":memory:"),
158+}),
159+});
160+await createPersonTable(testDb);
161+await testDb.insertInto("person").values({ name: "Ada" }).execute();
162+return testDb;
163+}
164+165+async function createPersonTable(testDb: Kysely<TestDatabase>): Promise<void> {
166+await testDb.schema
167+.createTable("person")
168+.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
169+.addColumn("name", "text", (col) => col.notNull())
170+.execute();
171+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。