mythix-orm 1.10.2 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/connection/connection-base.js +4 -20
- package/lib/connection/literals/literal-base.js +20 -1
- package/lib/connection/query-generator-base.d.ts +1 -15
- package/lib/connection/query-generator-base.js +55 -583
- package/lib/field.js +9 -2
- package/lib/model.d.ts +0 -2
- package/lib/model.js +58 -71
- package/lib/query-engine/field-scope.js +57 -24
- package/lib/query-engine/model-scope.js +232 -35
- package/lib/query-engine/query-engine-base.js +46 -13
- package/lib/query-engine/query-engine.d.ts +18 -4
- package/lib/query-engine/query-engine.js +47 -54
- package/lib/types/concrete/datetime-type.js +1 -1
- package/lib/types/concrete/serialized-type.js +2 -2
- package/lib/types/virtual/model-type.js +3 -3
- package/lib/types/virtual/relational-type-base.js +24 -24
- package/lib/utils/index.js +2 -2
- package/lib/utils/misc-utils.d.ts +0 -1
- package/lib/utils/misc-utils.js +0 -24
- package/lib/utils/model-utils.js +17 -17
- package/lib/utils/query-utils.d.ts +7 -0
- package/lib/utils/query-utils.js +175 -4
- package/package.json +1 -1
|
@@ -3,11 +3,128 @@
|
|
|
3
3
|
const Nife = require('nife');
|
|
4
4
|
const ProxyClass = require('../proxy-class');
|
|
5
5
|
const QueryEngineBase = require('./query-engine-base');
|
|
6
|
+
const QueryUtils = require('../utils/query-utils');
|
|
6
7
|
const {
|
|
7
8
|
LiteralBase,
|
|
8
9
|
DistinctLiteral,
|
|
9
10
|
} = require('../connection/literals');
|
|
10
11
|
|
|
12
|
+
function applyOrderClause(extraData, ...args) {
|
|
13
|
+
let entities = Nife.arrayFlatten(args);
|
|
14
|
+
|
|
15
|
+
entities = Nife.toArray(entities).map((value) => {
|
|
16
|
+
if (value == null)
|
|
17
|
+
return;
|
|
18
|
+
|
|
19
|
+
// Pass literals directly through
|
|
20
|
+
if (LiteralBase.isLiteral(value))
|
|
21
|
+
return value;
|
|
22
|
+
|
|
23
|
+
// Is the projection a field?
|
|
24
|
+
if (value.Model && value.fieldName)
|
|
25
|
+
return `${value.Model.getModelName()}:${value.fieldName}`;
|
|
26
|
+
|
|
27
|
+
if (!Nife.instanceOf(value, 'string'))
|
|
28
|
+
throw new Error('QueryEngine::ModelScope::ORDER: Invalid value provided. All values provided must be strings, fields, or literals. If you want to change the sort order of a given column, add "+" (ASC) or "-" (DESC) to be beginning of the field name. Example: .ORDER("+createdAt"), or .ORDER([ "-name", "+createdAt" ]).');
|
|
29
|
+
|
|
30
|
+
return value;
|
|
31
|
+
}).filter(Boolean);
|
|
32
|
+
|
|
33
|
+
let context = this.getOperationContext();
|
|
34
|
+
let order = this.margeFields(
|
|
35
|
+
context.order,
|
|
36
|
+
entities,
|
|
37
|
+
extraData,
|
|
38
|
+
{ isOrderBy: true },
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
this._pushOperationOntoStack({
|
|
42
|
+
control: true,
|
|
43
|
+
operator: 'ORDER',
|
|
44
|
+
queryProp: 'ORDER',
|
|
45
|
+
value: entities,
|
|
46
|
+
order,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return this._fetchScope('model');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function wrapOrderClause(func) {
|
|
53
|
+
const applyQueryOrder = (_order, replace) => {
|
|
54
|
+
let query = this;
|
|
55
|
+
let order = Nife.toArray(_order).filter(Boolean);
|
|
56
|
+
|
|
57
|
+
let asc = order.filter((thisOrder) => {
|
|
58
|
+
if (!Nife.instanceOf(thisOrder, 'string'))
|
|
59
|
+
return true;
|
|
60
|
+
|
|
61
|
+
if (thisOrder.charAt(0) === '-')
|
|
62
|
+
return false;
|
|
63
|
+
|
|
64
|
+
return true;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
let desc = order.filter((thisOrder) => {
|
|
68
|
+
if (!Nife.instanceOf(thisOrder, 'string'))
|
|
69
|
+
return false;
|
|
70
|
+
|
|
71
|
+
if (thisOrder.charAt(0) !== '-')
|
|
72
|
+
return false;
|
|
73
|
+
|
|
74
|
+
return true;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (Nife.isNotEmpty(asc)) {
|
|
78
|
+
asc = asc.map((thisOrder) => {
|
|
79
|
+
if (!Nife.instanceOf(thisOrder, 'string'))
|
|
80
|
+
return thisOrder;
|
|
81
|
+
|
|
82
|
+
return thisOrder.replace(/^\+/, '');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// eslint-disable-next-line new-cap
|
|
86
|
+
query = (replace) ? ASC(asc) : ASC('+', asc);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (Nife.isNotEmpty(desc)) {
|
|
90
|
+
desc = desc.map((thisOrder) => {
|
|
91
|
+
if (!Nife.instanceOf(thisOrder, 'string'))
|
|
92
|
+
return thisOrder;
|
|
93
|
+
|
|
94
|
+
return thisOrder.replace(/^-/, '');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// eslint-disable-next-line new-cap
|
|
98
|
+
query = (replace) ? DESC(desc) : DESC('+', desc);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return query;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const DESC = (...args) => {
|
|
105
|
+
return applyOrderClause.call(this, { direction: '-' }, ...args);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const ASC = (...args) => {
|
|
109
|
+
return applyOrderClause.call(this, { direction: '+' }, ...args);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const ADD = (...args) => {
|
|
113
|
+
return applyQueryOrder(args, false);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const REPLACE = (...args) => {
|
|
117
|
+
return applyQueryOrder(args, true);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
func.DESC = DESC;
|
|
121
|
+
func.ASC = ASC;
|
|
122
|
+
func.ADD = ADD;
|
|
123
|
+
func.REPLACE = REPLACE;
|
|
124
|
+
|
|
125
|
+
return func;
|
|
126
|
+
}
|
|
127
|
+
|
|
11
128
|
class ModelScope extends QueryEngineBase {
|
|
12
129
|
_getField(fieldName) {
|
|
13
130
|
let Model = this.currentContext.Model;
|
|
@@ -46,18 +163,22 @@ class ModelScope extends QueryEngineBase {
|
|
|
46
163
|
return this.currentContext.queryEngineScope.toString(...args);
|
|
47
164
|
}
|
|
48
165
|
|
|
166
|
+
margeFields(currentFields, incomingFields, extraData, options) {
|
|
167
|
+
return QueryUtils.margeFields(this, currentFields, incomingFields, extraData, options);
|
|
168
|
+
}
|
|
169
|
+
|
|
49
170
|
NOT = ProxyClass.autoCall(function() {
|
|
50
|
-
this._pushOperationOntoStack({ logical: true, operator: 'NOT', not: !this.currentContext.not });
|
|
171
|
+
this._pushOperationOntoStack({ logical: true, operator: 'NOT', queryProp: 'NOT', not: !this.currentContext.not });
|
|
51
172
|
return this._fetchScope('model');
|
|
52
173
|
});
|
|
53
174
|
|
|
54
175
|
AND = ProxyClass.autoCall(function(value) {
|
|
55
|
-
this._pushOperationOntoStack({ logical: true, operator: 'AND', and: true, or: false, not: false, value });
|
|
176
|
+
this._pushOperationOntoStack({ logical: true, operator: 'AND', queryProp: 'AND', and: true, or: false, not: false, value });
|
|
56
177
|
return this._fetchScope('model');
|
|
57
178
|
});
|
|
58
179
|
|
|
59
180
|
OR = ProxyClass.autoCall(function(value) {
|
|
60
|
-
this._pushOperationOntoStack({ logical: true, operator: 'OR', and: false, or: true, not: false, value });
|
|
181
|
+
this._pushOperationOntoStack({ logical: true, operator: 'OR', queryProp: 'OR', and: false, or: true, not: false, value });
|
|
61
182
|
return this._fetchScope('model');
|
|
62
183
|
});
|
|
63
184
|
|
|
@@ -67,7 +188,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
67
188
|
throw new Error('QueryEngine::ModelScope::LIMIT: Value provided must be a valid positive number, or Infinity.');
|
|
68
189
|
|
|
69
190
|
value = Math.round(value);
|
|
70
|
-
this._pushOperationOntoStack({ control: true, operator: 'LIMIT', value, limit: value });
|
|
191
|
+
this._pushOperationOntoStack({ control: true, operator: 'LIMIT', queryProp: 'LIMIT', value, limit: value });
|
|
71
192
|
|
|
72
193
|
return this._fetchScope('model');
|
|
73
194
|
}
|
|
@@ -78,32 +199,93 @@ class ModelScope extends QueryEngineBase {
|
|
|
78
199
|
throw new Error('QueryEngine::ModelScope::OFFSET: Value provided must be a valid positive number.');
|
|
79
200
|
|
|
80
201
|
value = Math.round(value);
|
|
81
|
-
this._pushOperationOntoStack({ control: true, operator: 'OFFSET', value, offset: value });
|
|
202
|
+
this._pushOperationOntoStack({ control: true, operator: 'OFFSET', queryProp: 'OFFSET', value, offset: value });
|
|
82
203
|
|
|
83
204
|
return this._fetchScope('model');
|
|
84
205
|
}
|
|
85
206
|
|
|
86
|
-
ORDER(...args) {
|
|
87
|
-
|
|
207
|
+
ORDER = wrapOrderClause.call(this, (...args) => {
|
|
208
|
+
return applyOrderClause.call(this, { direction: '+' }, ...args);
|
|
209
|
+
});
|
|
88
210
|
|
|
89
|
-
|
|
211
|
+
GROUP_BY(...args) {
|
|
212
|
+
let entities = Nife.arrayFlatten(args);
|
|
213
|
+
|
|
214
|
+
entities = Nife.toArray(entities).map((value) => {
|
|
90
215
|
if (value == null)
|
|
91
|
-
return
|
|
216
|
+
return;
|
|
217
|
+
|
|
218
|
+
// Pass literals directly through
|
|
219
|
+
if (LiteralBase.isLiteral(value))
|
|
220
|
+
return value;
|
|
221
|
+
|
|
222
|
+
// Is the projection a field?
|
|
223
|
+
if (value.Model && value.fieldName)
|
|
224
|
+
return `${value.Model.getModelName()}:${value.fieldName}`;
|
|
92
225
|
|
|
93
226
|
if (!Nife.instanceOf(value, 'string'))
|
|
94
|
-
throw new Error('QueryEngine::ModelScope::
|
|
227
|
+
throw new Error('QueryEngine::ModelScope::GROUP_BY: Invalid value provided. All values provided must be strings, fields, or literals. If you want to change the sort order of a given column, add "+" (ASC) or "-" (DESC) to be beginning of the field name. Example: .ORDER("+createdAt"), or .ORDER([ "-name", "+createdAt" ]).');
|
|
95
228
|
|
|
96
|
-
return
|
|
229
|
+
return value;
|
|
230
|
+
}).filter(Boolean);
|
|
231
|
+
|
|
232
|
+
let context = this.getOperationContext();
|
|
233
|
+
let groupBy = this.margeFields(
|
|
234
|
+
context.groupBy,
|
|
235
|
+
entities,
|
|
236
|
+
{},
|
|
237
|
+
{ isGroupBy: true },
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
this._pushOperationOntoStack({
|
|
241
|
+
control: true,
|
|
242
|
+
operator: 'GROUP_BY',
|
|
243
|
+
queryProp: 'GROUP_BY',
|
|
244
|
+
value: entities,
|
|
245
|
+
groupBy,
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return this._fetchScope('model');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
HAVING(query) {
|
|
252
|
+
this._pushOperationOntoStack({ control: true, operator: 'HAVING', queryProp: 'HAVING', value: query, having: query });
|
|
253
|
+
return this._fetchScope('model');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
EXISTS(_query) {
|
|
257
|
+
let query = _query;
|
|
258
|
+
let queryContext = (QueryEngineBase.isQuery(query)) ? query.getOperationContext() : null;
|
|
259
|
+
if (!queryContext || !queryContext.hasCondition)
|
|
260
|
+
throw new Error('QueryEngine::ModelScope::EXISTS: Provided value must be a query with conditions.');
|
|
261
|
+
|
|
262
|
+
if (!queryContext.projection) {
|
|
263
|
+
let Model = queryContext.Model;
|
|
264
|
+
let pkField = Model.getPrimaryKeyField();
|
|
265
|
+
|
|
266
|
+
if (pkField)
|
|
267
|
+
query = query.clone().PROJECT(pkField);
|
|
268
|
+
else
|
|
269
|
+
throw new Error('QueryEngine::ModelScope::EXISTS: Provided query must have only a single field projected.');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
this._pushOperationOntoStack({
|
|
273
|
+
condition: true,
|
|
274
|
+
operator: 'EXISTS',
|
|
275
|
+
inverseOperator: 'NOT EXISTS',
|
|
276
|
+
queryProp: 'EXISTS',
|
|
277
|
+
value: query,
|
|
278
|
+
having: query,
|
|
279
|
+
hasCondition: true,
|
|
97
280
|
});
|
|
98
281
|
|
|
99
|
-
this._pushOperationOntoStack({ control: true, operator: 'ORDER', value: values, order: values });
|
|
100
282
|
return this._fetchScope('model');
|
|
101
283
|
}
|
|
102
284
|
|
|
103
285
|
PROJECT(...args) {
|
|
104
|
-
let
|
|
286
|
+
let entities = Nife.arrayFlatten(args);
|
|
105
287
|
|
|
106
|
-
|
|
288
|
+
entities = Nife.toArray(entities).map((value) => {
|
|
107
289
|
if (value == null)
|
|
108
290
|
return;
|
|
109
291
|
|
|
@@ -119,63 +301,78 @@ class ModelScope extends QueryEngineBase {
|
|
|
119
301
|
if (value.Model && value.fieldName)
|
|
120
302
|
return value;
|
|
121
303
|
|
|
122
|
-
if (!Nife.instanceOf(value, 'string'))
|
|
123
|
-
|
|
304
|
+
if (!Nife.instanceOf(value, 'string')) {
|
|
305
|
+
console.log(entities);
|
|
306
|
+
throw new Error(`QueryEngine::ModelScope::PROJECT: Invalid value provided [${value.toString()}]. All values provided must be strings.`);
|
|
307
|
+
}
|
|
124
308
|
|
|
125
309
|
return value;
|
|
126
310
|
}).filter(Boolean);
|
|
127
311
|
|
|
128
|
-
this.
|
|
312
|
+
let context = this.getOperationContext();
|
|
313
|
+
let projection = this.margeFields(
|
|
314
|
+
context.projection,
|
|
315
|
+
entities,
|
|
316
|
+
{},
|
|
317
|
+
{ isProjection: true },
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
this._pushOperationOntoStack({
|
|
321
|
+
control: true,
|
|
322
|
+
operator: 'PROJECT',
|
|
323
|
+
queryProp: 'PROJECT',
|
|
324
|
+
value: entities,
|
|
325
|
+
projection,
|
|
326
|
+
});
|
|
327
|
+
|
|
129
328
|
return this._fetchScope('model');
|
|
130
329
|
}
|
|
131
330
|
|
|
132
331
|
DISTINCT = ProxyClass.autoCall(function(fullyQualifiedName) {
|
|
133
332
|
let currentQuery = this;
|
|
134
333
|
let distinctValue = fullyQualifiedName;
|
|
334
|
+
let context = this.getOperationContext();
|
|
135
335
|
|
|
136
336
|
if (arguments.length === 0) {
|
|
137
|
-
let context = this.getOperationContext();
|
|
138
337
|
let rootModel = context.rootModel;
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
currentQuery = this.PROJECT(`-${rootModel.getModelName()}:${pkFieldName}`);
|
|
338
|
+
if (rootModel) {
|
|
339
|
+
let pkFieldName = rootModel.getPrimaryKeyFieldName();
|
|
340
|
+
if (pkFieldName)
|
|
341
|
+
distinctValue = new DistinctLiteral(`${rootModel.getModelName()}:${pkFieldName}`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!distinctValue)
|
|
345
|
+
distinctValue = new DistinctLiteral();
|
|
148
346
|
} else if (fullyQualifiedName) {
|
|
149
347
|
distinctValue = new DistinctLiteral(fullyQualifiedName);
|
|
150
|
-
currentQuery = this.PROJECT(`-${fullyQualifiedName}`);
|
|
151
348
|
}
|
|
152
349
|
|
|
153
|
-
currentQuery._pushOperationOntoStack({
|
|
350
|
+
currentQuery._pushOperationOntoStack({ sqlFunc: true, operator: 'DISTINCT', queryProp: 'DISTINCT', value: distinctValue, distinct: distinctValue });
|
|
154
351
|
return this._fetchScope('model');
|
|
155
352
|
});
|
|
156
353
|
|
|
157
354
|
INNER_JOIN = ProxyClass.autoCall(function() {
|
|
158
|
-
this._pushOperationOntoStack({
|
|
355
|
+
this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'INNER_JOIN', value: 'inner', joinType: 'inner', joinOuter: false });
|
|
159
356
|
return this._fetchScope('model');
|
|
160
357
|
});
|
|
161
358
|
|
|
162
359
|
LEFT_JOIN = ProxyClass.autoCall(function(outerJoin) {
|
|
163
|
-
this._pushOperationOntoStack({
|
|
360
|
+
this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'LEFT_JOIN', value: 'left', joinType: 'left', joinOuter: !!outerJoin });
|
|
164
361
|
return this._fetchScope('model');
|
|
165
362
|
});
|
|
166
363
|
|
|
167
364
|
RIGHT_JOIN = ProxyClass.autoCall(function(outerJoin) {
|
|
168
|
-
this._pushOperationOntoStack({
|
|
365
|
+
this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'RIGHT_JOIN', value: 'right', joinType: 'right', joinOuter: !!outerJoin });
|
|
169
366
|
return this._fetchScope('model');
|
|
170
367
|
});
|
|
171
368
|
|
|
172
369
|
FULL_JOIN = ProxyClass.autoCall(function(outerJoin) {
|
|
173
|
-
this._pushOperationOntoStack({
|
|
370
|
+
this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'FULL_JOIN', value: 'full', joinType: 'full', joinOuter: !!outerJoin });
|
|
174
371
|
return this._fetchScope('model');
|
|
175
372
|
});
|
|
176
373
|
|
|
177
374
|
CROSS_JOIN = ProxyClass.autoCall(function() {
|
|
178
|
-
this._pushOperationOntoStack({
|
|
375
|
+
this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'CROSS_JOIN', value: 'cross', joinType: 'cross', joinOuter: false });
|
|
179
376
|
return this._fetchScope('model');
|
|
180
377
|
});
|
|
181
378
|
|
|
@@ -183,7 +380,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
183
380
|
if (!(Nife.instanceOf(type, 'string') || LiteralBase.isLiteral(type)))
|
|
184
381
|
throw new Error('QueryEngine::ModelScope::JOIN: Invalid value provided. Value must be a valid string or Literal specifying JOIN type.');
|
|
185
382
|
|
|
186
|
-
this._pushOperationOntoStack({
|
|
383
|
+
this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'JOIN', value: type, joinType: type, joinOuter: false });
|
|
187
384
|
return this._fetchScope('model');
|
|
188
385
|
}
|
|
189
386
|
}
|
|
@@ -13,8 +13,8 @@ class QueryEngineBase extends ProxyClass {
|
|
|
13
13
|
return uuid++;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
static
|
|
17
|
-
return !!(value && value.
|
|
16
|
+
static isQueryOperationContext(value) {
|
|
17
|
+
return !!(value && value.isQueryOperationContext);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
static isQuery(value) {
|
|
@@ -33,7 +33,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
static
|
|
36
|
+
static queryOperationInfo(queryContext) {
|
|
37
37
|
let contextParams = {
|
|
38
38
|
hasCondition: false,
|
|
39
39
|
hasField: false,
|
|
@@ -124,8 +124,10 @@ class QueryEngineBase extends ProxyClass {
|
|
|
124
124
|
let modelName = Model.getModelName();
|
|
125
125
|
let context = this.currentContext;
|
|
126
126
|
let extra = {};
|
|
127
|
+
let isFirst = !context.rootModel;
|
|
128
|
+
let connection = this.getConnection();
|
|
127
129
|
|
|
128
|
-
if (
|
|
130
|
+
if (isFirst) {
|
|
129
131
|
extra.rootModelName = modelName;
|
|
130
132
|
extra.rootModel = Model;
|
|
131
133
|
}
|
|
@@ -141,13 +143,10 @@ class QueryEngineBase extends ProxyClass {
|
|
|
141
143
|
throw new Error(`QueryEngine: Model "${Model.getModelName()}" is on a different connection dialect than the current query dialect of "${context.dialect}". You can not match different connection dialects in the same query.`);
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
if (!dialect)
|
|
145
|
-
|
|
146
|
-
if (connection)
|
|
147
|
-
dialect = connection.dialect;
|
|
148
|
-
}
|
|
146
|
+
if (!dialect && connection)
|
|
147
|
+
dialect = connection.dialect;
|
|
149
148
|
|
|
150
|
-
let newContext = this._inheritContext(context, 'model', { operator: 'MODEL', Model, modelName, dialect }, extra);
|
|
149
|
+
let newContext = this._inheritContext(context, 'model', { operator: 'MODEL', queryProp: 'Model', Model, modelName, dialect, value: modelName }, extra);
|
|
151
150
|
let newScope = new ModelScopeClass(newContext);
|
|
152
151
|
|
|
153
152
|
// We shouldn't add this scope if this is
|
|
@@ -155,6 +154,9 @@ class QueryEngineBase extends ProxyClass {
|
|
|
155
154
|
if (context.Model !== Model)
|
|
156
155
|
context.operationStack.push(newContext);
|
|
157
156
|
|
|
157
|
+
if (isFirst)
|
|
158
|
+
newScope = newScope.PROJECT(Model);
|
|
159
|
+
|
|
158
160
|
// But we always need to return the scope
|
|
159
161
|
// for the proxy to work properly
|
|
160
162
|
return newScope;
|
|
@@ -171,7 +173,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
171
173
|
extra.rootField = Field;
|
|
172
174
|
}
|
|
173
175
|
|
|
174
|
-
let newContext = this._inheritContext(context, 'field', { operator: 'FIELD', fieldName, Field }, extra);
|
|
176
|
+
let newContext = this._inheritContext(context, 'field', { operator: 'FIELD', queryProp: 'Field', fieldName, Field, value: fieldName }, extra);
|
|
175
177
|
let newScope = new FieldScopeClass(newContext);
|
|
176
178
|
|
|
177
179
|
// We shouldn't add this scope if this is
|
|
@@ -223,7 +225,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
223
225
|
let currentContext = operationStack[operationStack.length - 1];
|
|
224
226
|
return currentContext || context;
|
|
225
227
|
},
|
|
226
|
-
set:
|
|
228
|
+
set: () => {},
|
|
227
229
|
},
|
|
228
230
|
});
|
|
229
231
|
}
|
|
@@ -289,7 +291,6 @@ class QueryEngineBase extends ProxyClass {
|
|
|
289
291
|
else
|
|
290
292
|
console.log(`${operator} -> ${queryPart.value}`);
|
|
291
293
|
}
|
|
292
|
-
|
|
293
294
|
}
|
|
294
295
|
|
|
295
296
|
_pushOperationOntoStack(queryPart, _context) {
|
|
@@ -409,6 +410,38 @@ class QueryEngineBase extends ProxyClass {
|
|
|
409
410
|
let checkContextKeys = _checkContextKeys || [ 'value' ];
|
|
410
411
|
walkQueries(this, null, null, 0);
|
|
411
412
|
}
|
|
413
|
+
|
|
414
|
+
getAllModelsUsedInQuery() {
|
|
415
|
+
let Models = new Set();
|
|
416
|
+
let query = this.getOperationStack();
|
|
417
|
+
|
|
418
|
+
for (let i = 0, il = query.length; i < il; i++) {
|
|
419
|
+
let queryPart = query[i];
|
|
420
|
+
|
|
421
|
+
if (Object.prototype.hasOwnProperty.call(queryPart, 'operator') && queryPart.operator === 'MODEL') {
|
|
422
|
+
let Model = queryPart.Model;
|
|
423
|
+
Models.add(Model);
|
|
424
|
+
} else if (Object.prototype.hasOwnProperty.call(queryPart, 'condition') && queryPart.condition === true) {
|
|
425
|
+
let operatorValue = queryPart.value;
|
|
426
|
+
if (!QueryEngineBase.isQuery(operatorValue) || operatorValue.queryHasConditions())
|
|
427
|
+
continue;
|
|
428
|
+
|
|
429
|
+
let SubModels = operatorValue.getAllModelsUsedInQuery();
|
|
430
|
+
for (let j = 0, jl = SubModels.length; j < jl; j++) {
|
|
431
|
+
let Model = SubModels[j];
|
|
432
|
+
Models.add(Model);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
let allModels = Array.from(Models.values());
|
|
438
|
+
return allModels;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
isModelUsedInQuery(Model) {
|
|
442
|
+
let allModels = this.getAllModelsUsedInQuery();
|
|
443
|
+
return (allModels.indexOf(Model) >= 0);
|
|
444
|
+
}
|
|
412
445
|
}
|
|
413
446
|
|
|
414
447
|
module.exports = QueryEngineBase;
|
|
@@ -19,9 +19,9 @@ export declare interface CallableInterface {
|
|
|
19
19
|
export declare class QueryEngine<T = ConnectionBase> {
|
|
20
20
|
// QueryEngineBase
|
|
21
21
|
static generateID(): number;
|
|
22
|
-
static
|
|
22
|
+
static isQueryOperationContext(value: any): boolean;
|
|
23
23
|
static isQuery(value: any): boolean;
|
|
24
|
-
static
|
|
24
|
+
static queryOperationInfo(queryContext: GenericObject): { hasCondition: boolean; hasField: boolean; hasModel: boolean; };
|
|
25
25
|
|
|
26
26
|
public getModelScopeClass(): QueryEngine;
|
|
27
27
|
public getFieldScopeClass(): QueryEngine;
|
|
@@ -48,6 +48,7 @@ export declare class QueryEngine<T = ConnectionBase> {
|
|
|
48
48
|
public filter(callback: (operation: GenericObject, index: number, operations: Array<GenericObject>, query: QueryEngine) => GenericObject): QueryEngine;
|
|
49
49
|
public map(callback: (operation: GenericObject, index: number, operations: Array<GenericObject>, query: QueryEngine) => GenericObject): QueryEngine;
|
|
50
50
|
public walk(callback: (query: QueryEngine, parent: GenericObject | null, contextKey: string, depth: number) => GenericObject, checkContextKeys?: Array<string>): void;
|
|
51
|
+
public getAllModelsUsedInQuery(): Array<ModelClass>;
|
|
51
52
|
|
|
52
53
|
// QueryEngine
|
|
53
54
|
public getModelScopeClass(): QueryEngineClass;
|
|
@@ -78,8 +79,21 @@ export declare class QueryEngine<T = ConnectionBase> {
|
|
|
78
79
|
public Field(fieldName: string): QueryEngine;
|
|
79
80
|
public LIMIT(value: number): QueryEngine;
|
|
80
81
|
public OFFSET(value: number): QueryEngine;
|
|
81
|
-
public
|
|
82
|
-
public
|
|
82
|
+
public GROUP_BY(...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>): QueryEngine;
|
|
83
|
+
public HAVING(query: QueryEngine): QueryEngine;
|
|
84
|
+
public EXISTS(query: QueryEngine): QueryEngine;
|
|
85
|
+
public PROJECT(...args: Array<string | ModelClass | LiteralBase | Field | Array<string | ModelClass | LiteralBase | Field>>): QueryEngine;
|
|
86
|
+
|
|
87
|
+
declare public ORDER: {
|
|
88
|
+
(...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>): QueryEngine;
|
|
89
|
+
|
|
90
|
+
ASC: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
|
|
91
|
+
DESC: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
|
|
92
|
+
ADD: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
|
|
93
|
+
REPLACE: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
|
|
94
|
+
|
|
95
|
+
name: QueryEngine;
|
|
96
|
+
};
|
|
83
97
|
|
|
84
98
|
declare public NOT: {
|
|
85
99
|
(): QueryEngine;
|