diff --git a/src/db/ModelRelation.ts b/src/db/ModelRelation.ts index 0762e8f..76ed0f0 100644 --- a/src/db/ModelRelation.ts +++ b/src/db/ModelRelation.ts @@ -5,7 +5,8 @@ import ModelFactory from "./ModelFactory"; export default abstract class ModelRelation { protected readonly model: S; protected readonly foreignFactory: ModelFactory; - protected readonly query: ModelQuery; + private readonly query: ModelQuery; + protected readonly queryModifiers: QueryModifier[] = []; protected readonly filters: ModelFilter[] = []; protected cachedModels?: R; @@ -18,7 +19,7 @@ export default abstract class ModelRelation; public constraint(queryModifier: QueryModifier): this { - queryModifier(this.query); + this.queryModifiers.push(queryModifier); return this; } @@ -27,13 +28,19 @@ export default abstract class ModelRelation { + for (const modifier of this.queryModifiers) modifier(this.query); + this.queryModifiers.splice(0, this.queryModifiers.length); // Empty modifier now that they were applied + return this.query; + } + public abstract getModelID(): any; protected abstract async compute(query: ModelQuery): Promise; public async get(): Promise { if (this.cachedModels === undefined) { - this.cachedModels = await this.compute(this.query); + this.cachedModels = await this.compute(this.getFinalQuery()); } return this.cachedModels; } @@ -65,7 +72,7 @@ export class OneModelRelation extends ModelRel } protected async compute(query: ModelQuery): Promise { - this.query.where(this.dbProperties.foreignKey, this.getModelID()); + this.getFinalQuery().where(this.dbProperties.foreignKey, this.getModelID()); return await query.first(); } @@ -85,8 +92,9 @@ export class OneModelRelation extends ModelRel const ids = relations.map(r => r.getModelID()).filter(id => id !== null && id !== undefined); if (ids.length === 0) return []; - this.query.where(this.dbProperties.foreignKey, ids, WhereTest.IN); - return await this.query.get(); + const query = this.getFinalQuery(); + query.where(this.dbProperties.foreignKey, ids, WhereTest.IN); + return await query.get(); } public async populate(models: ModelQueryResult): Promise { @@ -116,7 +124,7 @@ export class ManyModelRelation extends ModelRe } protected async compute(query: ModelQuery): Promise { - this.query.where(this.dbProperties.foreignKey, this.getModelID()); + this.getFinalQuery().where(this.dbProperties.foreignKey, this.getModelID()); return await query.get(); } @@ -138,8 +146,9 @@ export class ManyModelRelation extends ModelRe const ids = relations.map(r => r.getModelID()).filter(id => id !== null && id !== undefined); if (ids.length === 0) return []; - this.query.where(this.dbProperties.foreignKey, ids, WhereTest.IN); - return await this.query.get(); + const query = this.getFinalQuery(); + query.where(this.dbProperties.foreignKey, ids, WhereTest.IN); + return await query.get(); } public async populate(models: ModelQueryResult): Promise { @@ -154,9 +163,10 @@ export class ManyThroughModelRelation extends constructor(model: S, foreignFactory: ModelFactory, dbProperties: PivotRelationDatabaseProperties) { super(model, foreignFactory); this.dbProperties = dbProperties; - this.query + this.constraint(query => query .leftJoin(`${this.dbProperties.pivotTable} as pivot`) - .on(`pivot.${this.dbProperties.foreignPivotKey}`, `${this.foreignFactory.table}.${this.dbProperties.foreignKey}`); + .on(`pivot.${this.dbProperties.foreignPivotKey}`, `${this.foreignFactory.table}.${this.dbProperties.foreignKey}`) + ); } public clone(): ManyThroughModelRelation { @@ -168,7 +178,7 @@ export class ManyThroughModelRelation extends } protected async compute(query: ModelQuery): Promise { - this.query.where(`pivot.${this.dbProperties.localPivotKey}`, this.getModelID()); + this.getFinalQuery().where(`pivot.${this.dbProperties.localPivotKey}`, this.getModelID()); return await query.get(); } @@ -190,9 +200,10 @@ export class ManyThroughModelRelation extends const ids = relations.map(r => r.getModelID()); if (ids.length === 0) return []; - this.query.where(`pivot.${this.dbProperties.localPivotKey}`, ids, WhereTest.IN); - this.query.pivot(`pivot.${this.dbProperties.localPivotKey}`, `pivot.${this.dbProperties.foreignPivotKey}`); - return await this.query.get(); + const query = this.getFinalQuery(); + query.where(`pivot.${this.dbProperties.localPivotKey}`, ids, WhereTest.IN); + query.pivot(`pivot.${this.dbProperties.localPivotKey}`, `pivot.${this.dbProperties.foreignPivotKey}`); + return await query.get(); } public async populate(models: ModelQueryResult): Promise {