ModelQuery: add groupWhere and test it
This commit is contained in:
parent
823f5d0d26
commit
e29b6369af
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wms-core",
|
||||
"version": "0.21.10",
|
||||
"version": "0.21.11",
|
||||
"description": "Node web application framework and toolbelt.",
|
||||
"repository": "https://gitlab.com/ArisuOngaku/wms-core",
|
||||
"author": "Alice Gaudon <alice@gaudon.pro>",
|
||||
|
@ -5,7 +5,8 @@ import Pagination from "../Pagination";
|
||||
import ModelRelation from "./ModelRelation";
|
||||
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> {
|
||||
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 _leftJoin?: string;
|
||||
private _leftJoinOn: WhereFieldValue[] = [];
|
||||
private _where: WhereFieldValue[] = [];
|
||||
private _where: (WhereFieldValue | WhereFieldValueGroup)[] = [];
|
||||
private _limit?: number;
|
||||
private _offset?: number;
|
||||
private _sortBy?: string;
|
||||
@ -62,6 +63,27 @@ export default class ModelQuery<M extends Model> {
|
||||
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 {
|
||||
this._limit = limit;
|
||||
this._offset = offset;
|
||||
@ -154,11 +176,17 @@ export default class ModelQuery<M extends Model> {
|
||||
this.fields?.filter(v => v instanceof FieldValue)
|
||||
.flatMap(v => (<FieldValue>v).variables)
|
||||
.forEach(v => variables.push(v));
|
||||
this._where.flatMap(v => v.variables)
|
||||
this._where.flatMap(v => this.getVariables(v))
|
||||
.forEach(v => variables.push(v));
|
||||
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> {
|
||||
return await query(this.build(), this.variables, connection);
|
||||
}
|
||||
@ -327,4 +355,31 @@ class WhereFieldValue extends FieldValue {
|
||||
}
|
||||
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