Skip to content

Commit 8260aa2

Browse files
committed
feat: batch mutation
1 parent 8d6818c commit 8260aa2

25 files changed

Lines changed: 4178 additions & 136 deletions

packages/entity-database-adapter-knex-testing-utils/src/StubPostgresDatabaseAdapter.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,56 @@ export class StubPostgresDatabaseAdapter<
227227
}
228228
}
229229

230+
protected async batchInsertInternalAsync(
231+
_queryInterface: any,
232+
tableName: string,
233+
objects: readonly object[],
234+
): Promise<object[]> {
235+
const objectCollection = this.getObjectCollectionForTable(tableName);
236+
237+
const idField = getDatabaseFieldForEntityField(
238+
this.entityConfiguration2,
239+
this.entityConfiguration2.idField,
240+
);
241+
const insertedObjects: object[] = [];
242+
for (const object of objects) {
243+
const objectToInsert = {
244+
[idField]: this.generateRandomID(),
245+
...object,
246+
};
247+
objectCollection.push(objectToInsert);
248+
insertedObjects.push(objectToInsert);
249+
}
250+
return insertedObjects;
251+
}
252+
253+
protected async batchUpdateInternalAsync(
254+
_queryInterface: any,
255+
tableName: string,
256+
tableIdField: string,
257+
ids: readonly any[],
258+
object: object,
259+
): Promise<object[]> {
260+
if (Object.keys(object).length === 0) {
261+
throw new Error(`Empty batch update (${tableIdField} IN (${ids.join(', ')}))`);
262+
}
263+
264+
const objectCollection = this.getObjectCollectionForTable(tableName);
265+
const updatedObjects: object[] = [];
266+
267+
for (const id of ids) {
268+
const objectIndex = objectCollection.findIndex((obj) => obj[tableIdField] === id);
269+
if (objectIndex >= 0) {
270+
objectCollection[objectIndex] = {
271+
...objectCollection[objectIndex],
272+
...object,
273+
};
274+
updatedObjects.push(objectCollection[objectIndex]);
275+
}
276+
}
277+
return updatedObjects;
278+
}
279+
230280
protected async insertInternalAsync(
231281
_queryInterface: any,
232282
tableName: string,
@@ -277,6 +327,25 @@ export class StubPostgresDatabaseAdapter<
277327
return [objectCollection[objectIndex]];
278328
}
279329

330+
protected async batchDeleteInternalAsync(
331+
_queryInterface: any,
332+
tableName: string,
333+
tableIdField: string,
334+
ids: readonly any[],
335+
): Promise<number> {
336+
const objectCollection = this.getObjectCollectionForTable(tableName);
337+
let count = 0;
338+
339+
for (const id of ids) {
340+
const objectIndex = objectCollection.findIndex((obj) => obj[tableIdField] === id);
341+
if (objectIndex >= 0) {
342+
objectCollection.splice(objectIndex, 1);
343+
count++;
344+
}
345+
}
346+
return count;
347+
}
348+
280349
protected async deleteInternalAsync(
281350
_queryInterface: any,
282351
tableName: string,

packages/entity-database-adapter-knex/src/PostgresEntityDatabaseAdapter.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,35 @@ export class PostgresEntityDatabaseAdapter<
250250
return await wrapNativePostgresCallAsync(() => query);
251251
}
252252

253+
protected async batchInsertInternalAsync(
254+
queryInterface: Knex,
255+
tableName: string,
256+
objects: readonly object[],
257+
): Promise<object[]> {
258+
return await wrapNativePostgresCallAsync(() =>
259+
queryInterface
260+
.insert([...objects])
261+
.into(tableName)
262+
.returning('*'),
263+
);
264+
}
265+
266+
protected async batchUpdateInternalAsync(
267+
queryInterface: Knex,
268+
tableName: string,
269+
tableIdField: string,
270+
ids: readonly any[],
271+
object: object,
272+
): Promise<object[]> {
273+
return await wrapNativePostgresCallAsync(() =>
274+
queryInterface
275+
.update(object)
276+
.into(tableName)
277+
.whereIn(tableIdField, [...ids])
278+
.returning('*'),
279+
);
280+
}
281+
253282
protected async insertInternalAsync(
254283
queryInterface: Knex,
255284
tableName: string,
@@ -272,6 +301,20 @@ export class PostgresEntityDatabaseAdapter<
272301
);
273302
}
274303

304+
protected async batchDeleteInternalAsync(
305+
queryInterface: Knex,
306+
tableName: string,
307+
tableIdField: string,
308+
ids: readonly any[],
309+
): Promise<number> {
310+
return await wrapNativePostgresCallAsync(() =>
311+
queryInterface
312+
.into(tableName)
313+
.whereIn(tableIdField, [...ids])
314+
.del(),
315+
);
316+
}
317+
275318
protected async deleteInternalAsync(
276319
queryInterface: Knex,
277320
tableName: string,

0 commit comments

Comments
 (0)