From 56849eae4df6087cff80287c88a0b8340b33f2fe Mon Sep 17 00:00:00 2001 From: sebas Date: Thu, 4 Apr 2024 09:04:50 +0100 Subject: [PATCH 1/2] adds delete method with repeated filter code --- .../interfaces/event-repository.interface.ts | 8 +++ .../src/event-repository-sqlite.ts | 61 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/packages/common/src/interfaces/event-repository.interface.ts b/packages/common/src/interfaces/event-repository.interface.ts index 5aa6889a..e2f69f53 100644 --- a/packages/common/src/interfaces/event-repository.interface.ts +++ b/packages/common/src/interfaces/event-repository.interface.ts @@ -42,6 +42,14 @@ export abstract class EventRepository { */ abstract find(filter: Filter): Promise | Event[]; + /** + * If filter is present, events that match the filter are deleted. + * If no filter is present, all events are deleted. + * + * @param filter Query filter + */ + abstract delete(filter?: Filter): Promise; + /** * This method doesn't need to be implemented. It's just a helper method for * finding one event. And it will call `find` method internally. diff --git a/packages/event-repository-sqlite/src/event-repository-sqlite.ts b/packages/event-repository-sqlite/src/event-repository-sqlite.ts index f448eac2..423aaeca 100644 --- a/packages/event-repository-sqlite/src/event-repository-sqlite.ts +++ b/packages/event-repository-sqlite/src/event-repository-sqlite.ts @@ -172,6 +172,67 @@ export class EventRepositorySqlite extends EventRepository { return rows.map(this.toEvent); } + async delete(filter?: Filter): Promise { + let innerJoinClauses: string[] = []; + let whereClauses: string[] = []; + let whereValues: (string | number)[] = []; + + if (filter) { + const { ids, authors, kinds, since, until } = filter; + const genericTags = this.extractGenericTagsFrom(filter); + + if (genericTags.length) { + genericTags.forEach((genericTags, index) => { + const alias = `g${index + 1}`; + innerJoinClauses.push( + `INNER JOIN generic_tags ${alias} ON ${alias}.event_id = e.id`, + ); + whereClauses.push( + `${alias}.tag IN (${genericTags.map(() => '?').join(',')})`, + ); + whereValues.push(...genericTags); + }); + } + + if (ids?.length) { + whereClauses.push(`id IN (${ids.map(() => '?').join(',')})`); + whereValues.push(...ids); + } + + if (authors?.length) { + whereClauses.push(`author IN (${authors.map(() => '?').join(',')})`); + whereValues.push(...authors); + } + + if (kinds?.length) { + whereClauses.push(`kind IN (${kinds.map(() => '?').join(',')})`); + whereValues.push(...kinds); + } + + if (since) { + whereClauses.push(`created_at >= ?`); + whereValues.push(since); + } + + if (until) { + whereClauses.push(`created_at <= ?`); + whereValues.push(until); + } + } + + const whereClause = + whereClauses.length > 0 ? `WHERE ${whereClauses.join(' AND ')}` : ''; + const deleteResult = this.db + .prepare( + ` + DELETE FROM events ${whereClause}; + `, + ) + .run(whereValues); + + return deleteResult.changes; + } + private async findFromGenericTags( filter: Filter, genericTags: string[][], From a83c814005b7f284845399b4845a45dd24afbaa8 Mon Sep 17 00:00:00 2001 From: sebas Date: Thu, 4 Apr 2024 13:21:44 +0100 Subject: [PATCH 2/2] extract filter logic to function --- .../src/event-repository-sqlite.ts | 145 ++++++++---------- 1 file changed, 62 insertions(+), 83 deletions(-) diff --git a/packages/event-repository-sqlite/src/event-repository-sqlite.ts b/packages/event-repository-sqlite/src/event-repository-sqlite.ts index 423aaeca..d5325094 100644 --- a/packages/event-repository-sqlite/src/event-repository-sqlite.ts +++ b/packages/event-repository-sqlite/src/event-repository-sqlite.ts @@ -9,6 +9,12 @@ import * as BetterSqlite3 from 'better-sqlite3'; import { readFileSync, readdirSync } from 'fs'; import * as path from 'path'; +interface FilterSqlClauses { + innerJoinClauses: string[]; + whereClauses: string[]; + whereValues: (string | number)[]; +} + export class EventRepositorySqlite extends EventRepository { private db: BetterSqlite3.Database; @@ -108,7 +114,7 @@ export class EventRepositorySqlite extends EventRepository { } async find(filter: Filter): Promise { - const { ids, authors, kinds, since, until, limit } = filter; + const { limit } = filter; if (limit === 0) return []; @@ -117,47 +123,7 @@ export class EventRepositorySqlite extends EventRepository { return this.findFromGenericTags(filter, genericTags); } - const innerJoinClauses: string[] = []; - const whereClauses: string[] = []; - const whereValues: (string | number)[] = []; - - if (genericTags.length) { - genericTags.forEach((genericTags, index) => { - const alias = `g${index + 1}`; - innerJoinClauses.push( - `INNER JOIN generic_tags ${alias} ON ${alias}.event_id = e.id`, - ); - whereClauses.push( - `${alias}.tag IN (${genericTags.map(() => '?').join(',')})`, - ); - whereValues.push(...genericTags); - }); - } - - if (ids?.length) { - whereClauses.push(`id IN (${ids.map(() => '?').join(',')})`); - whereValues.push(...ids); - } - - if (authors?.length) { - whereClauses.push(`author IN (${authors.map(() => '?').join(',')})`); - whereValues.push(...authors); - } - - if (kinds?.length) { - whereClauses.push(`kind IN (${kinds.map(() => '?').join(',')})`); - whereValues.push(...kinds); - } - - if (since) { - whereClauses.push(`created_at >= ?`); - whereValues.push(since); - } - - if (until) { - whereClauses.push(`created_at <= ?`); - whereValues.push(until); - } + const { innerJoinClauses, whereClauses, whereValues } = this.sqlClausesFrom(filter); const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(' AND ')}` : ''; @@ -173,51 +139,11 @@ export class EventRepositorySqlite extends EventRepository { } async delete(filter?: Filter): Promise { - let innerJoinClauses: string[] = []; let whereClauses: string[] = []; let whereValues: (string | number)[] = []; if (filter) { - const { ids, authors, kinds, since, until } = filter; - const genericTags = this.extractGenericTagsFrom(filter); - - if (genericTags.length) { - genericTags.forEach((genericTags, index) => { - const alias = `g${index + 1}`; - innerJoinClauses.push( - `INNER JOIN generic_tags ${alias} ON ${alias}.event_id = e.id`, - ); - whereClauses.push( - `${alias}.tag IN (${genericTags.map(() => '?').join(',')})`, - ); - whereValues.push(...genericTags); - }); - } - - if (ids?.length) { - whereClauses.push(`id IN (${ids.map(() => '?').join(',')})`); - whereValues.push(...ids); - } - - if (authors?.length) { - whereClauses.push(`author IN (${authors.map(() => '?').join(',')})`); - whereValues.push(...authors); - } - - if (kinds?.length) { - whereClauses.push(`kind IN (${kinds.map(() => '?').join(',')})`); - whereValues.push(...kinds); - } - - if (since) { - whereClauses.push(`created_at >= ?`); - whereValues.push(since); - } - - if (until) { - whereClauses.push(`created_at <= ?`); - whereValues.push(until); - } + ({ whereClauses, whereValues } = this.sqlClausesFrom(filter)); } const whereClause = @@ -391,4 +317,57 @@ export class EventRepositorySqlite extends EventRepository { executedMigrations: migrationsToRun, }; } + + private sqlClausesFrom(filter: Filter): FilterSqlClauses { + const innerJoinClauses: string[] = []; + const whereClauses: string[] = []; + const whereValues: (string | number)[] = []; + + const { ids, authors, kinds, since, until } = filter; + const genericTags = this.extractGenericTagsFrom(filter); + + if (genericTags.length) { + genericTags.forEach((genericTags, index) => { + const alias = `g${index + 1}`; + innerJoinClauses.push( + `INNER JOIN generic_tags ${alias} ON ${alias}.event_id = e.id`, + ); + whereClauses.push( + `${alias}.tag IN (${genericTags.map(() => '?').join(',')})`, + ); + whereValues.push(...genericTags); + }); + } + + if (ids?.length) { + whereClauses.push(`id IN (${ids.map(() => '?').join(',')})`); + whereValues.push(...ids); + } + + if (authors?.length) { + whereClauses.push(`author IN (${authors.map(() => '?').join(',')})`); + whereValues.push(...authors); + } + + if (kinds?.length) { + whereClauses.push(`kind IN (${kinds.map(() => '?').join(',')})`); + whereValues.push(...kinds); + } + + if (since) { + whereClauses.push(`created_at >= ?`); + whereValues.push(since); + } + + if (until) { + whereClauses.push(`created_at <= ?`); + whereValues.push(until); + } + + return { + innerJoinClauses, + whereClauses, + whereValues, + }; + } }