Skip to content

Commit

Permalink
perf(sql): use multi-insert when populating m:n collections
Browse files Browse the repository at this point in the history
  • Loading branch information
B4nan committed Nov 14, 2019
1 parent 01a57e8 commit 5ece088
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 15 deletions.
12 changes: 9 additions & 3 deletions lib/drivers/AbstractSqlDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,19 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra

for (const k of owners) {
const prop = props[k];
const pivotProp2 = this.getPivotInverseProperty(prop);
const qb1 = this.createQueryBuilder(prop.pivotTable, ctx, true);
await qb1.delete({ [pivotProp2.name]: pk }).execute('run', false);
await this.connection.execute(qb1.getKnex().where({ [prop.joinColumn]: pk }).delete());
const items = [];

for (const item of collections[k]) {
items.push({ [prop.joinColumn]: pk, [prop.inverseJoinColumn]: item });
}

if (this.platform.allowsMultiInsert()) {
const qb2 = this.createQueryBuilder(prop.pivotTable, ctx, true);
await qb2.insert({ [pivotProp2.name]: pk, [prop.type]: item }).execute('run', false);
await this.connection.execute(qb2.getKnex().insert(items));
} else {
await Utils.runSerial(items, item => this.createQueryBuilder(prop.pivotTable, ctx, true).insert(item).execute('run', false));
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions lib/platforms/Platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export abstract class Platform {
return false;
}

allowsMultiInsert() {
return true;
}

/**
* Normalizes primary key wrapper to scalar value (e.g. mongodb's ObjectId to string)
*/
Expand Down
4 changes: 4 additions & 0 deletions lib/platforms/SqlitePlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export class SqlitePlatform extends Platform {
return true;
}

allowsMultiInsert() {
return false;
}

getCurrentTimestampSQL(length: number): string {
return super.getCurrentTimestampSQL(0);
}
Expand Down
24 changes: 12 additions & 12 deletions lib/query/QueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,17 @@ export class QueryBuilder<T extends AnyEntity<T> = AnyEntity> {
return qb;
}

getKnex(): KnexQueryBuilder {
const tableName = this.helper.getTableName(this.entityName) + ([QueryType.SELECT, QueryType.COUNT].includes(this.type) ? ` as ${this.alias}` : '');
const qb = this.knex(tableName);

if (this.context) {
qb.transacting(this.context);
}

return qb;
}

private joinReference(field: string, alias: string, cond: Dictionary, type: 'leftJoin' | 'innerJoin' | 'pivotJoin'): string[] {
const [fromAlias, fromField] = this.helper.splitField(field);
const entityName = this._aliasMap[fromAlias];
Expand Down Expand Up @@ -342,7 +353,7 @@ export class QueryBuilder<T extends AnyEntity<T> = AnyEntity> {
}

private getQueryBase(): KnexQueryBuilder {
const qb = this.createBuilder();
const qb = this.getKnex();

switch (this.type) {
case QueryType.SELECT:
Expand Down Expand Up @@ -377,17 +388,6 @@ export class QueryBuilder<T extends AnyEntity<T> = AnyEntity> {
return qb;
}

private createBuilder(): KnexQueryBuilder {
const tableName = this.helper.getTableName(this.entityName) + ([QueryType.SELECT, QueryType.COUNT].includes(this.type) ? ` as ${this.alias}` : '');
const qb = this.knex(tableName);

if (this.context) {
qb.transacting(this.context);
}

return qb;
}

private finalize(): void {
if (this.finalized) {
return;
Expand Down

0 comments on commit 5ece088

Please sign in to comment.