From 969ab18b9655682d64701eb49fbff7b08570426c Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Tue, 8 Sep 2020 18:12:39 +0200 Subject: [PATCH] ModelRelation: sort recursive relations by tree --- package.json | 2 +- src/db/ModelQuery.ts | 15 ++++++++++----- src/db/ModelRelation.ts | 9 +++++++-- test/ModelQuery.test.ts | 14 +++++++++++--- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 3820be3..1246216 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wms-core", - "version": "0.22.0-rc.8", + "version": "0.22.0-rc.11", "description": "Node web application framework and toolbelt.", "repository": "https://gitlab.com/ArisuOngaku/wms-core", "author": "Alice Gaudon ", diff --git a/src/db/ModelQuery.ts b/src/db/ModelQuery.ts index 6e9dcd2..7ac5da3 100644 --- a/src/db/ModelQuery.ts +++ b/src/db/ModelQuery.ts @@ -45,6 +45,7 @@ export default class ModelQuery implements WhereFieldConsumer, fields?: SelectFields) { this.type = type; @@ -109,7 +110,7 @@ export default class ModelQuery implements WhereFieldConsumer { const parts = relation.split('.'); - this.relations.push(parts[0]); + if (this.relations.indexOf(parts[0]) < 0) this.relations.push(parts[0]); if (parts.length > 1) { if (!this.subRelations[parts[0]]) this.subRelations[parts[0]] = []; this.subRelations[parts[0]].push(parts.slice(1).join('.')); @@ -135,9 +136,10 @@ export default class ModelQuery implements WhereFieldConsumer implements WhereFieldConsumer extends } export class RecursiveModelRelation extends ManyModelRelation { - public constructor(model: M, foreignModelType: ModelType, dbProperties: RelationDatabaseProperties) { + private readonly reverse: boolean; + + public constructor(model: M, foreignModelType: ModelType, dbProperties: RelationDatabaseProperties, reverse: boolean = false) { super(model, foreignModelType, dbProperties); - this.constraint(query => query.recursive(this.dbProperties)); + this.constraint(query => query.recursive(this.dbProperties, reverse)); + this.reverse = reverse; } public clone(): RecursiveModelRelation { @@ -221,6 +224,8 @@ export class RecursiveModelRelation extends ManyModelRelation cached[this.dbProperties.localKey] === model[this.dbProperties.foreignKey]) )); } while (count !== this.cachedModels.length); + + if (this.reverse) this.cachedModels!.reverse(); } } diff --git a/test/ModelQuery.test.ts b/test/ModelQuery.test.ts index 5c97257..dae8ddf 100644 --- a/test/ModelQuery.test.ts +++ b/test/ModelQuery.test.ts @@ -59,11 +59,19 @@ describe('Test ModelQuery', () => { const query = ModelQuery.select({table: 'model'} as unknown as ModelFactory, '*'); query.where('f1', 'v1'); query.leftJoin('test').on('model.j1', 'test.j2'); - query.recursive({localKey: 'local', foreignKey: 'foreign'}); - query.sortBy('f2', 'ASC').limit(8); + query.recursive({localKey: 'local', foreignKey: 'foreign'}, false); + query.limit(8); - expect(query.toString(true)).toBe("WITH RECURSIVE cte AS (SELECT `model`.* FROM `model` WHERE `f1`=? UNION SELECT o.* FROM `model` AS o, cte AS c WHERE o.`foreign`=c.`local`) SELECT * FROM cte LEFT JOIN `test` ON `model`.`j1`=`test`.`j2` ORDER BY `f2` ASC LIMIT 8"); + expect(query.toString(true)).toBe("WITH RECURSIVE cte AS (SELECT `model`.*,1 AS __depth, CONCAT(`local`) AS __path FROM `model` WHERE `f1`=? UNION SELECT o.*,c.__depth + 1,CONCAT(c.__path,'/',o.`local`) AS __path FROM `model` AS o, cte AS c WHERE o.`foreign`=c.`local`) SELECT * FROM cte LEFT JOIN `test` ON `model`.`j1`=`test`.`j2` ORDER BY __path ASC LIMIT 8"); expect(query.variables).toStrictEqual(['v1']); + + const reversedQuery = ModelQuery.select({table: 'model'} as unknown as ModelFactory, '*'); + reversedQuery.where('f1', 'v1'); + reversedQuery.leftJoin('test').on('model.j1', 'test.j2'); + reversedQuery.recursive({localKey: 'local', foreignKey: 'foreign'}, true); + + expect(reversedQuery.toString(true)).toBe("WITH RECURSIVE cte AS (SELECT `model`.*,1 AS __depth, CONCAT(`foreign`) AS __path FROM `model` WHERE `f1`=? UNION SELECT o.*,c.__depth + 1,CONCAT(c.__path,'/',o.`foreign`) AS __path FROM `model` AS o, cte AS c WHERE o.`foreign`=c.`local`) SELECT * FROM cte LEFT JOIN `test` ON `model`.`j1`=`test`.`j2` ORDER BY __path DESC"); + expect(reversedQuery.variables).toStrictEqual(['v1']); }); test('union queries', () => {