ModelQuery: add groupWhere and test it
This commit is contained in:
parent
823f5d0d26
commit
e29b6369af
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wms-core",
|
"name": "wms-core",
|
||||||
"version": "0.21.10",
|
"version": "0.21.11",
|
||||||
"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>",
|
||||||
|
@ -5,7 +5,8 @@ import Pagination from "../Pagination";
|
|||||||
import ModelRelation from "./ModelRelation";
|
import ModelRelation from "./ModelRelation";
|
||||||
import ModelFactory from "./ModelFactory";
|
import ModelFactory from "./ModelFactory";
|
||||||
|
|
||||||
export default class ModelQuery<M extends Model> {
|
|
||||||
|
export default class ModelQuery<M extends Model> implements WhereFieldConsumer<M> {
|
||||||
public static select<M extends Model>(factory: ModelFactory<M>, ...fields: string[]): ModelQuery<M> {
|
public static select<M extends Model>(factory: ModelFactory<M>, ...fields: string[]): ModelQuery<M> {
|
||||||
return new ModelQuery(QueryType.SELECT, factory, fields.length > 0 ? fields : ['*']);
|
return new ModelQuery(QueryType.SELECT, factory, fields.length > 0 ? fields : ['*']);
|
||||||
}
|
}
|
||||||
@ -32,7 +33,7 @@ export default class ModelQuery<M extends Model> {
|
|||||||
private fields: (string | SelectFieldValue | UpdateFieldValue)[];
|
private fields: (string | SelectFieldValue | UpdateFieldValue)[];
|
||||||
private _leftJoin?: string;
|
private _leftJoin?: string;
|
||||||
private _leftJoinOn: WhereFieldValue[] = [];
|
private _leftJoinOn: WhereFieldValue[] = [];
|
||||||
private _where: WhereFieldValue[] = [];
|
private _where: (WhereFieldValue | WhereFieldValueGroup)[] = [];
|
||||||
private _limit?: number;
|
private _limit?: number;
|
||||||
private _offset?: number;
|
private _offset?: number;
|
||||||
private _sortBy?: string;
|
private _sortBy?: string;
|
||||||
@ -62,6 +63,27 @@ export default class ModelQuery<M extends Model> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public groupWhere(setter: (query: WhereFieldConsumer<M>) => void, operator: WhereOperator = WhereOperator.AND): this {
|
||||||
|
this._where.push(new WhereFieldValueGroup(this.collectWheres(setter), operator));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private collectWheres(setter: (query: WhereFieldConsumer<M>) => void): (WhereFieldValue | WhereFieldValueGroup)[] {
|
||||||
|
const query = this;
|
||||||
|
const wheres: (WhereFieldValue | WhereFieldValueGroup)[] = [];
|
||||||
|
setter({
|
||||||
|
where(field: string, value: string | Date | ModelQuery<any> | any, test: WhereTest = WhereTest.EQ, operator: WhereOperator = WhereOperator.AND) {
|
||||||
|
wheres.push(new WhereFieldValue(field, value, false, test, operator));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
groupWhere(setter: (query: WhereFieldConsumer<M>) => void, operator: WhereOperator = WhereOperator.AND) {
|
||||||
|
wheres.push(new WhereFieldValueGroup(query.collectWheres(setter), operator))
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return wheres;
|
||||||
|
}
|
||||||
|
|
||||||
public limit(limit: number, offset: number = 0): this {
|
public limit(limit: number, offset: number = 0): this {
|
||||||
this._limit = limit;
|
this._limit = limit;
|
||||||
this._offset = offset;
|
this._offset = offset;
|
||||||
@ -154,11 +176,17 @@ export default class ModelQuery<M extends Model> {
|
|||||||
this.fields?.filter(v => v instanceof FieldValue)
|
this.fields?.filter(v => v instanceof FieldValue)
|
||||||
.flatMap(v => (<FieldValue>v).variables)
|
.flatMap(v => (<FieldValue>v).variables)
|
||||||
.forEach(v => variables.push(v));
|
.forEach(v => variables.push(v));
|
||||||
this._where.flatMap(v => v.variables)
|
this._where.flatMap(v => this.getVariables(v))
|
||||||
.forEach(v => variables.push(v));
|
.forEach(v => variables.push(v));
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getVariables(where: WhereFieldValue | WhereFieldValueGroup): any[] {
|
||||||
|
return where instanceof WhereFieldValueGroup ?
|
||||||
|
where.fields.flatMap(v => this.getVariables(v)) :
|
||||||
|
where.variables;
|
||||||
|
}
|
||||||
|
|
||||||
public async execute(connection?: Connection): Promise<QueryResult> {
|
public async execute(connection?: Connection): Promise<QueryResult> {
|
||||||
return await query(this.build(), this.variables, connection);
|
return await query(this.build(), this.variables, connection);
|
||||||
}
|
}
|
||||||
@ -328,3 +356,30 @@ class WhereFieldValue extends FieldValue {
|
|||||||
return this._test;
|
return this._test;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WhereFieldValueGroup {
|
||||||
|
public readonly fields: (WhereFieldValue | WhereFieldValueGroup)[];
|
||||||
|
public readonly operator: WhereOperator;
|
||||||
|
|
||||||
|
public constructor(fields: (WhereFieldValue | WhereFieldValueGroup)[], operator: WhereOperator) {
|
||||||
|
this.fields = fields;
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toString(first: boolean = true): string {
|
||||||
|
let str = `${first ? '' : ` ${this.operator} `}(`;
|
||||||
|
let firstField = true;
|
||||||
|
for (const field of this.fields) {
|
||||||
|
str += field.toString(firstField);
|
||||||
|
firstField = false;
|
||||||
|
}
|
||||||
|
str += ')';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WhereFieldConsumer<M extends Model> {
|
||||||
|
where(field: string, value: string | Date | ModelQuery<any> | any, test?: WhereTest, operator?: WhereOperator): this;
|
||||||
|
|
||||||
|
groupWhere(setter: (query: WhereFieldConsumer<M>) => void, operator?: WhereOperator): this;
|
||||||
|
}
|
||||||
|
16
test/ModelQuery.test.ts
Normal file
16
test/ModelQuery.test.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import ModelQuery, {WhereOperator} from "../src/db/ModelQuery";
|
||||||
|
import ModelFactory from "../src/db/ModelFactory";
|
||||||
|
import Model from "../src/db/Model";
|
||||||
|
|
||||||
|
describe('Test ModelQuery', () => {
|
||||||
|
test('groupWhere generates proper query', () => {
|
||||||
|
const query = ModelQuery.select({table: 'model'} as unknown as ModelFactory<Model>, '*');
|
||||||
|
query.where('f1', 'v1');
|
||||||
|
query.groupWhere(q => q.where('f2', 'v2').where('f3', 'v3')
|
||||||
|
.groupWhere(q => q.where('f4', 'v4'), WhereOperator.OR))
|
||||||
|
.where('f5', 'v5');
|
||||||
|
|
||||||
|
expect(query.toString(true)).toBe('SELECT * FROM model WHERE `f1`=? AND (`f2`=? AND `f3`=? OR (`f4`=?)) AND `f5`=? ');
|
||||||
|
expect(query.variables.length).toBe(5);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user