ModelRelation: sort recursive relations by tree
This commit is contained in:
parent
892b830dc4
commit
e08f4fb875
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wms-core",
|
"name": "wms-core",
|
||||||
"version": "0.22.0-rc.8",
|
"version": "0.22.0-rc.9",
|
||||||
"description": "Node web application framework and toolbelt.",
|
"description": "Node web application framework and toolbelt.",
|
||||||
"repository": "https://gitlab.com/ArisuOngaku/wms-core",
|
"repository": "https://gitlab.com/ArisuOngaku/wms-core",
|
||||||
"author": "Alice Gaudon <alice@gaudon.pro>",
|
"author": "Alice Gaudon <alice@gaudon.pro>",
|
||||||
|
@ -2,7 +2,7 @@ import {query, QueryResult} from "./MysqlConnectionManager";
|
|||||||
import {Connection} from "mysql";
|
import {Connection} from "mysql";
|
||||||
import Model from "./Model";
|
import Model from "./Model";
|
||||||
import Pagination from "../Pagination";
|
import Pagination from "../Pagination";
|
||||||
import ModelRelation, {RelationDatabaseProperties} from "./ModelRelation";
|
import ModelRelation, {RecursiveRelationDatabaseProperties} from "./ModelRelation";
|
||||||
import ModelFactory from "./ModelFactory";
|
import ModelFactory from "./ModelFactory";
|
||||||
|
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export default class ModelQuery<M extends Model> implements WhereFieldConsumer<M
|
|||||||
private readonly subRelations: { [relation: string]: string[] } = {};
|
private readonly subRelations: { [relation: string]: string[] } = {};
|
||||||
private _pivot?: string[];
|
private _pivot?: string[];
|
||||||
private _union?: ModelQueryUnion;
|
private _union?: ModelQueryUnion;
|
||||||
private _recursiveRelation?: RelationDatabaseProperties;
|
private _recursiveRelation?: RecursiveRelationDatabaseProperties;
|
||||||
|
|
||||||
private constructor(type: QueryType, factory: ModelFactory<M>, fields?: SelectFields) {
|
private constructor(type: QueryType, factory: ModelFactory<M>, fields?: SelectFields) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -135,7 +135,7 @@ export default class ModelQuery<M extends Model> implements WhereFieldConsumer<M
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public recursive(relation: RelationDatabaseProperties): this {
|
public recursive(relation: RecursiveRelationDatabaseProperties): this {
|
||||||
if (this.type !== QueryType.SELECT) throw new Error('Recursive queries are only implemented with SELECT.');
|
if (this.type !== QueryType.SELECT) throw new Error('Recursive queries are only implemented with SELECT.');
|
||||||
this._recursiveRelation = relation;
|
this._recursiveRelation = relation;
|
||||||
return this;
|
return this;
|
||||||
@ -191,10 +191,10 @@ export default class ModelQuery<M extends Model> implements WhereFieldConsumer<M
|
|||||||
if (this._recursiveRelation) {
|
if (this._recursiveRelation) {
|
||||||
const cteFields = fields.replace(RegExp(`${table}`, 'g'), 'o');
|
const cteFields = fields.replace(RegExp(`${table}`, 'g'), 'o');
|
||||||
query = `WITH RECURSIVE cte AS (`
|
query = `WITH RECURSIVE cte AS (`
|
||||||
+ `SELECT ${fields} FROM ${table}${where}`
|
+ `SELECT ${fields},1 AS __depth, ARRAY[\`${this._recursiveRelation.idKey}\`] AS __path FROM ${table}${where}`
|
||||||
+ ` UNION `
|
+ ` UNION `
|
||||||
+ `SELECT ${cteFields} FROM ${table} AS o, cte AS c WHERE o.\`${this._recursiveRelation.foreignKey}\`=c.\`${this._recursiveRelation.localKey}\``
|
+ `SELECT ${cteFields}, c.__depth + 1,c.__path || o.\`${this._recursiveRelation.idKey}\` FROM ${table} AS o, cte AS c WHERE o.\`${this._recursiveRelation.foreignKey}\`=c.\`${this._recursiveRelation.localKey}\``
|
||||||
+ `) SELECT * FROM cte${join}${orderBy}${limit}`;
|
+ `) SELECT * FROM cte${join}${orderBy || ` ORDER BY __path`}${limit}`;
|
||||||
} else {
|
} else {
|
||||||
query = `SELECT ${fields} FROM ${table}${join}${where}${orderBy}${limit}`;
|
query = `SELECT ${fields} FROM ${table}${join}${where}${orderBy}${limit}`;
|
||||||
}
|
}
|
||||||
|
@ -201,8 +201,11 @@ export class ManyThroughModelRelation<S extends Model, O extends Model> extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RecursiveModelRelation<M extends Model> extends ManyModelRelation<M, M> {
|
export class RecursiveModelRelation<M extends Model> extends ManyModelRelation<M, M> {
|
||||||
public constructor(model: M, foreignModelType: ModelType<M>, dbProperties: RelationDatabaseProperties) {
|
protected readonly dbProperties: RecursiveRelationDatabaseProperties;
|
||||||
|
|
||||||
|
public constructor(model: M, foreignModelType: ModelType<M>, dbProperties: RecursiveRelationDatabaseProperties) {
|
||||||
super(model, foreignModelType, dbProperties);
|
super(model, foreignModelType, dbProperties);
|
||||||
|
this.dbProperties = dbProperties;
|
||||||
this.constraint(query => query.recursive(this.dbProperties));
|
this.constraint(query => query.recursive(this.dbProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,3 +243,7 @@ export type PivotRelationDatabaseProperties = RelationDatabaseProperties & {
|
|||||||
localPivotKey: string;
|
localPivotKey: string;
|
||||||
foreignPivotKey: string;
|
foreignPivotKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RecursiveRelationDatabaseProperties = RelationDatabaseProperties & {
|
||||||
|
idKey: string;
|
||||||
|
};
|
||||||
|
@ -59,10 +59,10 @@ describe('Test ModelQuery', () => {
|
|||||||
const query = ModelQuery.select({table: 'model'} as unknown as ModelFactory<Model>, '*');
|
const query = ModelQuery.select({table: 'model'} as unknown as ModelFactory<Model>, '*');
|
||||||
query.where('f1', 'v1');
|
query.where('f1', 'v1');
|
||||||
query.leftJoin('test').on('model.j1', 'test.j2');
|
query.leftJoin('test').on('model.j1', 'test.j2');
|
||||||
query.recursive({localKey: 'local', foreignKey: 'foreign'});
|
query.recursive({localKey: 'local', foreignKey: 'foreign', idKey: 'foreign'});
|
||||||
query.sortBy('f2', 'ASC').limit(8);
|
query.sortBy('f2', 'ASC').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, ARRAY[`foreign`] AS __path FROM `model` WHERE `f1`=? UNION SELECT o.*, c.__depth + 1,c.__path || o.`foreign` 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.variables).toStrictEqual(['v1']);
|
expect(query.variables).toStrictEqual(['v1']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user