From 269f34b1887470772c437def6e45892f490ca5d8 Mon Sep 17 00:00:00 2001 From: called_D Date: Fri, 17 May 2024 13:27:15 +0900 Subject: [PATCH 1/2] add: transformD1ResultToKyselyQueryResult(results) --- src/index.ts | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/index.ts b/src/index.ts index a29d280..c3f768c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,7 @@ import { QueryCompiler, QueryResult, } from 'kysely'; -import type { D1Database } from '@cloudflare/workers-types'; +import type { D1Database, D1Result } from '@cloudflare/workers-types'; /** * Config for the D1 dialect. Pass your D1 instance to this object that you bound in `wrangler.toml`. @@ -87,6 +87,21 @@ class D1Driver implements Driver { async destroy(): Promise {} } +function transformD1ResultToKyselyQueryResult(results: D1Result): QueryResult { + const numAffectedRows = results.meta.changes > 0 ? BigInt(results.meta.changes) : undefined; + + return { + insertId: + results.meta.last_row_id === undefined || results.meta.last_row_id === null + ? undefined + : BigInt(results.meta.last_row_id), + rows: (results?.results as O[]) || [], + numAffectedRows, + // @ts-ignore deprecated in kysely >= 0.23, keep for backward compatibility. + numUpdatedOrDeletedRows: numAffectedRows, + }; +} + class D1Connection implements DatabaseConnection { #config: D1DialectConfig; // #transactionClient?: D1Connection @@ -107,18 +122,7 @@ class D1Connection implements DatabaseConnection { throw new Error(results.error); } - const numAffectedRows = results.meta.changes > 0 ? BigInt(results.meta.changes) : undefined; - - return { - insertId: - results.meta.last_row_id === undefined || results.meta.last_row_id === null - ? undefined - : BigInt(results.meta.last_row_id), - rows: (results?.results as O[]) || [], - numAffectedRows, - // @ts-ignore deprecated in kysely >= 0.23, keep for backward compatibility. - numUpdatedOrDeletedRows: numAffectedRows, - }; + return transformD1ResultToKyselyQueryResult(results); } async beginTransaction() { From a634b2629352c79de9e602ac1815f73925d348dd Mon Sep 17 00:00:00 2001 From: called_D Date: Fri, 17 May 2024 13:28:00 +0900 Subject: [PATCH 2/2] impl: batch() helper function --- src/index.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/index.ts b/src/index.ts index c3f768c..258cbf4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import { + Compilable, CompiledQuery, DatabaseConnection, DatabaseIntrospector, @@ -149,3 +150,39 @@ class D1Connection implements DatabaseConnection { throw new Error('D1 Driver does not support streaming'); } } + +type QueryOutput = Q extends Compilable ? O : never +/** + * Helper function of [Batch statements][0] + * + * ```typescript + * const results = await batch(env.DB, [ + * db.updateTable('kv').set({ value: '1' }).where('key', '=', key1), + * db.updateTable('kv').set({ value: '2' }).where('key', '=', key2), + * db.selectFrom('kv').selectAll().where('key', 'in', [key1, key2]), + * ] as const) + * const { rows } = results[2] + * ``` + * + * [0]: https://developers.cloudflare.com/d1/build-with-d1/d1-client-api/#batch-statements + */ +export async function batch( + database: D1Database, + queries: Q +): Promise<{ [P in keyof Q]: QueryResult> }> { + if (queries.length === 0) + return [] as { [P in keyof Q]: QueryResult> }; + + const results = await database.batch( + queries + .map((query) => query.compile()) + .map(({ sql, parameters }) => database.prepare(sql).bind(...parameters)) + ); + + const error = results.find((result) => result.error); + if (error) throw new Error(error.error); + + return results.map( + (result): QueryResult => transformD1ResultToKyselyQueryResult(result) + ) as { [P in keyof Q]: QueryResult> }; +}