mythix-orm 1.11.6 → 1.12.0
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/README.md +100 -9
- package/lib/connection/connection-base.js +173 -39
- package/lib/connection/literals/average-literal.js +67 -0
- package/lib/connection/literals/count-literal.js +80 -0
- package/lib/connection/literals/distinct-literal.js +71 -0
- package/lib/connection/literals/field-literal.js +54 -0
- package/lib/connection/literals/literal-base.d.ts +1 -0
- package/lib/connection/literals/literal-base.js +137 -2
- package/lib/connection/literals/literal-field-base.js +50 -0
- package/lib/connection/literals/literal.js +15 -0
- package/lib/connection/literals/max-literal.js +67 -0
- package/lib/connection/literals/min-literal.js +67 -0
- package/lib/connection/literals/sum-literal.js +67 -0
- package/lib/connection/query-generator-base.js +273 -0
- package/lib/field.js +1 -1
- package/lib/model.js +54 -2
- package/lib/proxy-class/proxy-class.js +156 -21
- package/lib/query-engine/field-scope.js +401 -9
- package/lib/query-engine/model-scope.js +572 -13
- package/lib/query-engine/query-engine-base.js +590 -30
- package/lib/query-engine/query-engine.d.ts +13 -2
- package/lib/query-engine/query-engine.js +525 -18
- package/lib/types/helpers/default-helpers.js +124 -0
- package/lib/types/type.js +297 -3
- package/lib/utils/async-store.js +80 -3
- package/package.json +1 -2
|
@@ -8,15 +8,67 @@ function generateID() {
|
|
|
8
8
|
return uuid++;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/// `QueryEngineBase` is the class that all other
|
|
12
|
+
/// query engine classes inherit from. It provides
|
|
13
|
+
/// "proxy" support for all class instances.
|
|
14
|
+
/// `QueryEngine`, `ModelScope`, and `FieldScope` all
|
|
15
|
+
/// inherit from this class.
|
|
16
|
+
///
|
|
17
|
+
/// Note:
|
|
18
|
+
/// `QueryEngineBase` is a sub-part of the `QueryEngine`, and so is generally referred to
|
|
19
|
+
/// simply as the `QueryEngine` as a whole. This is also the case for <see>ModelScope</see>,
|
|
20
|
+
/// and <see>FieldScope</see>, which also make up the `QueryEngine` as sub-parts,
|
|
21
|
+
/// and so are also often referred to simply as "the query engine".
|
|
11
22
|
class QueryEngineBase extends ProxyClass {
|
|
23
|
+
/// Used to generate unique "operation ids"
|
|
24
|
+
/// for the query operation stack.
|
|
25
|
+
///
|
|
26
|
+
/// Return: number
|
|
27
|
+
/// A unique id.
|
|
12
28
|
static generateID() {
|
|
13
29
|
return uuid++;
|
|
14
30
|
}
|
|
15
31
|
|
|
32
|
+
/// Check if the provided `value` is an "operation context".
|
|
33
|
+
///
|
|
34
|
+
/// The query engine works by creating an "operation stack",
|
|
35
|
+
/// that is an array of "operation contexts". Any time an
|
|
36
|
+
/// operation is carried out on the query engine, such as
|
|
37
|
+
/// selecting a new model for example `new QueryEngine({ connection }).Model('User')`
|
|
38
|
+
/// then an "operation" will be pushed onto the operation stack.
|
|
39
|
+
/// Each operation on the stack sets its `prototype` to the previous
|
|
40
|
+
/// operation on the stack using `Object.create`. This means that
|
|
41
|
+
/// all "operation contexts" on the stack also include all attributes
|
|
42
|
+
/// from all previous operations on the stack via the operation
|
|
43
|
+
/// `prototype`.
|
|
44
|
+
///
|
|
45
|
+
/// Use this method to check if any object is a valid "operation context"
|
|
46
|
+
/// from the query engine.
|
|
47
|
+
///
|
|
48
|
+
/// Arguments:
|
|
49
|
+
/// value: object
|
|
50
|
+
/// The value to check.
|
|
51
|
+
///
|
|
52
|
+
/// Return: boolean
|
|
53
|
+
/// Return `true` if the provided `value` is a query engine "operation context",
|
|
54
|
+
/// or `false` otherwise.
|
|
16
55
|
static isQueryOperationContext(value) {
|
|
17
56
|
return !!(value && value.isQueryOperationContext);
|
|
18
57
|
}
|
|
19
58
|
|
|
59
|
+
/// Check to see if the provided value is
|
|
60
|
+
/// an *instance* of a Mythix ORM <see>QueryEngineBase</see>.
|
|
61
|
+
/// It will return `true` if the provided value is an `instanceof`
|
|
62
|
+
/// <see>QueryEngineBase</see>, if the value's `constructor`
|
|
63
|
+
/// property has a truthy `_isMythixQueryEngine` property
|
|
64
|
+
/// (`value.constructor._isMythixQueryEngine`), or if the
|
|
65
|
+
/// provided value has a `getOperationContext` method.
|
|
66
|
+
///
|
|
67
|
+
/// Return: boolean
|
|
68
|
+
///
|
|
69
|
+
/// Arguments:
|
|
70
|
+
/// value: any
|
|
71
|
+
/// Value to check
|
|
20
72
|
static isQuery(value) {
|
|
21
73
|
if (!value)
|
|
22
74
|
return false;
|
|
@@ -24,7 +76,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
24
76
|
if (value instanceof QueryEngineBase)
|
|
25
77
|
return true;
|
|
26
78
|
|
|
27
|
-
if (value.
|
|
79
|
+
if (value._isMythixQueryEngine)
|
|
28
80
|
return true;
|
|
29
81
|
|
|
30
82
|
if (typeof value.getOperationContext === 'function')
|
|
@@ -33,16 +85,64 @@ class QueryEngineBase extends ProxyClass {
|
|
|
33
85
|
return false;
|
|
34
86
|
}
|
|
35
87
|
|
|
36
|
-
|
|
88
|
+
/// Get information about the query.
|
|
89
|
+
///
|
|
90
|
+
/// This method will return an object
|
|
91
|
+
/// containing certain keys that will
|
|
92
|
+
/// report on the status of the query.
|
|
93
|
+
///
|
|
94
|
+
/// Interface:
|
|
95
|
+
/// interface QueryInfo {
|
|
96
|
+
/// hasDistinct: boolean;
|
|
97
|
+
/// hasOrder: boolean;
|
|
98
|
+
/// hasProjection: boolean;
|
|
99
|
+
/// hasGroupBy: boolean;
|
|
100
|
+
/// hasHaving: boolean;
|
|
101
|
+
/// hasCondition: boolean;
|
|
102
|
+
/// hasTableJoins: boolean;
|
|
103
|
+
/// hasField: boolean;
|
|
104
|
+
/// hasModel: boolean;
|
|
105
|
+
/// }
|
|
106
|
+
///
|
|
107
|
+
/// Arguments:
|
|
108
|
+
/// query: <see>QueryEngine</see>
|
|
109
|
+
/// The query to get information on.
|
|
110
|
+
///
|
|
111
|
+
/// Return: QueryInfo
|
|
112
|
+
/// Return information relating to the query.
|
|
113
|
+
static getQueryOperationInfo(query) {
|
|
37
114
|
let contextParams = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
115
|
+
hasDistinct: false,
|
|
116
|
+
hasOrder: false,
|
|
117
|
+
hasProjection: false,
|
|
118
|
+
hasGroupBy: false,
|
|
119
|
+
hasHaving: false,
|
|
120
|
+
hasCondition: false,
|
|
121
|
+
hasTableJoins: false,
|
|
122
|
+
hasField: false,
|
|
123
|
+
hasModel: false,
|
|
41
124
|
};
|
|
42
125
|
|
|
43
|
-
if (!
|
|
126
|
+
if (!query)
|
|
44
127
|
return contextParams;
|
|
45
128
|
|
|
129
|
+
let queryContext = query.getOperationContext();
|
|
130
|
+
|
|
131
|
+
if (queryContext.distinct)
|
|
132
|
+
contextParams.hasDistinct = true;
|
|
133
|
+
|
|
134
|
+
if (queryContext.order)
|
|
135
|
+
contextParams.hasOrder = true;
|
|
136
|
+
|
|
137
|
+
if (queryContext.projection)
|
|
138
|
+
contextParams.hasProjection = true;
|
|
139
|
+
|
|
140
|
+
if (queryContext.groupBy)
|
|
141
|
+
contextParams.hasGroupBy = true;
|
|
142
|
+
|
|
143
|
+
if (queryContext.having)
|
|
144
|
+
contextParams.hasHaving = true;
|
|
145
|
+
|
|
46
146
|
if (queryContext.condition)
|
|
47
147
|
contextParams.hasCondition = true;
|
|
48
148
|
|
|
@@ -52,21 +152,126 @@ class QueryEngineBase extends ProxyClass {
|
|
|
52
152
|
if (queryContext.Model)
|
|
53
153
|
contextParams.hasModel = true;
|
|
54
154
|
|
|
155
|
+
contextParams.hasTableJoins = query.queryHasJoins();
|
|
156
|
+
|
|
55
157
|
return contextParams;
|
|
56
158
|
}
|
|
57
159
|
|
|
160
|
+
/// Get the `ModelScope` class that should be used
|
|
161
|
+
/// for the query. By default this will be <see>ModelScope</see>.
|
|
162
|
+
///
|
|
163
|
+
/// This is provided so that the end-user can overload the
|
|
164
|
+
/// query engine, adding custom functionality. You could for
|
|
165
|
+
/// example inherit from the default <see>ModelScope</see> class
|
|
166
|
+
/// and add extra functionality to the query engine. To do so,
|
|
167
|
+
/// you would overload this method on your own custom implementation
|
|
168
|
+
/// of `QueryEngine`, and would return your own custom `ModelScope`
|
|
169
|
+
/// class for use in the query engine.
|
|
170
|
+
///
|
|
171
|
+
/// A "model scope" is a sub-scope of the `QueryEngine` that defines
|
|
172
|
+
/// "model level operations". A model scope is returned by the query
|
|
173
|
+
/// engine as soon as a model is accessed, i.e. `User.where` would
|
|
174
|
+
/// return a `ModelScope` relating to the `User` model. A conditional
|
|
175
|
+
/// operation, such as `EQ` will also return a `ModelScope`... ready
|
|
176
|
+
/// for the next field to be specified. Scopes are used in the Mythix ORM
|
|
177
|
+
/// query engine so that you can't do anything funky... such as `User.where.EQ('value')`...
|
|
178
|
+
/// how can a model be equal to a value? It can't... so scopes are used
|
|
179
|
+
/// in the engine to ensure you can't do anything silly. This scope defines
|
|
180
|
+
/// all operations that can be applied to models.
|
|
181
|
+
///
|
|
182
|
+
/// Return: class inherits <see>ModelScope</see>
|
|
183
|
+
/// The class to use for "model scopes".
|
|
58
184
|
getModelScopeClass() {
|
|
59
185
|
return this.getQueryEngineScope().getModelScopeClass();
|
|
60
186
|
}
|
|
61
187
|
|
|
188
|
+
/// Get the `FieldScope` class that should be used
|
|
189
|
+
/// for the query. By default this will be <see>FieldScope</see>.
|
|
190
|
+
///
|
|
191
|
+
/// This is provided so that the end-user can overload the
|
|
192
|
+
/// query engine, adding custom functionality. You could for
|
|
193
|
+
/// example inherit from the default <see>FieldScope</see> class
|
|
194
|
+
/// and add extra functionality to the query engine. To do so,
|
|
195
|
+
/// you would overload this method on your own custom implementation
|
|
196
|
+
/// of `QueryEngine`, and would return your own custom `FieldScope`
|
|
197
|
+
/// class for use in the query engine.
|
|
198
|
+
///
|
|
199
|
+
/// A "field scope" is a sub-scope of the `QueryEngine` that defines
|
|
200
|
+
/// "field level operations". A field scope is returned by the query
|
|
201
|
+
/// engine as soon as a field is accessed, i.e. `User.where.id` would
|
|
202
|
+
/// return a `FieldScope` relating to the `User` model (the `id` field).
|
|
203
|
+
/// Scopes are used in the Mythix ORM query engine so that you can't do
|
|
204
|
+
/// anything funky... such as `User.where.EQ('value')`...
|
|
205
|
+
/// how can a model be equal to a value? It can't... so scopes are used
|
|
206
|
+
/// in the engine to ensure you can't do anything silly. This scope defines
|
|
207
|
+
/// all operations that can be applied to model fields.
|
|
208
|
+
///
|
|
209
|
+
/// Return: class inherits <see>FieldScope</see>
|
|
210
|
+
/// The class to use for "field scopes".
|
|
62
211
|
getFieldScopeClass() {
|
|
63
212
|
return this.getQueryEngineScope().getFieldScopeClass();
|
|
64
213
|
}
|
|
65
214
|
|
|
215
|
+
/// Get the `QueryEngine` class that should be used
|
|
216
|
+
/// for the query. By default this will be <see>QueryEngine</see>.
|
|
217
|
+
///
|
|
218
|
+
/// This is provided so that the end-user can overload the
|
|
219
|
+
/// query engine, adding custom functionality. You could for
|
|
220
|
+
/// example inherit from the default <see>QueryEngine</see> class
|
|
221
|
+
/// and add extra functionality to the query engine. To do so,
|
|
222
|
+
/// you would overload this method on your own custom implementation
|
|
223
|
+
/// of `QueryEngine`, and would return your own custom `QueryEngine`
|
|
224
|
+
/// class for use in the query engine.
|
|
225
|
+
///
|
|
226
|
+
/// A "query scope" is the "root scope" of a `QueryEngine` that defines
|
|
227
|
+
/// "root level operations". A root scope is returned by the query
|
|
228
|
+
/// engine as soon as the query is created, i.e. `new QueryEngine({ connection })` would
|
|
229
|
+
/// return a `QueryEngine`. Scopes are used in the Mythix ORM query engine so that
|
|
230
|
+
/// you can't do anything funky... such as `User.where.EQ('value')`...
|
|
231
|
+
/// how can a model be equal to a value? It can't... so scopes are used
|
|
232
|
+
/// in the engine to ensure you can't do anything silly. This scope defines
|
|
233
|
+
/// all operations that can be applied to the "root query", such as fetching
|
|
234
|
+
/// the operation stack, the operation context, mapping or filtering the query, etc...
|
|
235
|
+
///
|
|
236
|
+
/// Return: class inherits <see>QueryEngine</see>
|
|
237
|
+
/// The class to use for "root scopes". By default this method
|
|
238
|
+
/// will return the class used to initially create the query engine.
|
|
239
|
+
/// So for example if you create the query with your own custom class,
|
|
240
|
+
/// such as `new MyCustomQueryEngine({ connection })`, then this will
|
|
241
|
+
/// automatically return your class for you (`MyCustomQueryEngine` in this example).
|
|
66
242
|
getQueryEngineScopeClass() {
|
|
67
243
|
return this.getQueryEngineScope().constructor;
|
|
68
244
|
}
|
|
69
245
|
|
|
246
|
+
/// This "stacks" an incoming "operation context" on top
|
|
247
|
+
/// the previous context in the "operation stack". It will
|
|
248
|
+
/// also reset the `value` of the context to `undefined`, and
|
|
249
|
+
/// will generate a new `contextID` for this new context.
|
|
250
|
+
///
|
|
251
|
+
/// Note:
|
|
252
|
+
/// You probably should not use this method directly unless you know
|
|
253
|
+
/// exactly what you are doing. Instead you should use the <see>QueryEngineBase._pushOperationOntoStack</see>,
|
|
254
|
+
/// <see>QueryEngineBase._newQueryEngineScope</see>, <see>QueryEngineBase._newModelScope</see>, or
|
|
255
|
+
/// <see>QueryEngineBase._newFieldScope</see> to push operations onto the stack.
|
|
256
|
+
///
|
|
257
|
+
/// Arguments:
|
|
258
|
+
/// context: object
|
|
259
|
+
/// The previous (top-most) "operation context" on top the "operation stack".
|
|
260
|
+
/// name?: string
|
|
261
|
+
/// The name for this operation context. This is only ever used when the "scope"
|
|
262
|
+
/// changes by using one of <see>QueryEngineBase._newQueryEngineScope</see>,
|
|
263
|
+
/// <see>QueryEngineBase._newModelScope</see>, or <see>QueryEngineBase._newFieldScope</see>.
|
|
264
|
+
/// These methods will set a "scope name" so that it can later be fetched using
|
|
265
|
+
/// <see>QueryEngineBase._fetchScope</see>. Scope names will only ever be one of
|
|
266
|
+
/// `'queryEngine'`, `'model'`, or `'field'`.
|
|
267
|
+
/// ...args?: Array<object>
|
|
268
|
+
/// Other objects to merge into the context.
|
|
269
|
+
///
|
|
270
|
+
/// Return: object
|
|
271
|
+
/// Return the new "operation context", with the `args` objects merged in. This new
|
|
272
|
+
/// context will have a `prototype` that is set to the `context` provided.
|
|
273
|
+
///
|
|
274
|
+
/// See: QueryEngineBase._fetchScope
|
|
70
275
|
_inheritContext(context, name, ...args) {
|
|
71
276
|
let newContext = Object.assign(
|
|
72
277
|
Object.create(context),
|
|
@@ -85,6 +290,35 @@ class QueryEngineBase extends ProxyClass {
|
|
|
85
290
|
return newContext;
|
|
86
291
|
}
|
|
87
292
|
|
|
293
|
+
/// Fetch a previous named scope.
|
|
294
|
+
///
|
|
295
|
+
/// This is useful when you want to change scopes during query operations.
|
|
296
|
+
/// For example, if you just did a field-level operation inside a <see>FieldScope</see>,
|
|
297
|
+
/// such as `query.field.EQ('test')`, then you need to return a "model scope" so
|
|
298
|
+
/// the user can continue chaining operations. Do to so, you would call: `return this._fetchScope('model');`
|
|
299
|
+
/// which will fetch and return the *current* "model scope".
|
|
300
|
+
///
|
|
301
|
+
/// If the specified scope is not found (as a previous scope in the "operation stack"),
|
|
302
|
+
/// then this method will simply return `this`. Because this isn't often desired, and could
|
|
303
|
+
/// be a problem, this method takes `scopeNames` as an array of scopes to "fall back" to
|
|
304
|
+
/// if the specified scope can not be found. For example, one could do: `return this._fetchScope('model', 'queryEngine');`
|
|
305
|
+
/// to request the `'model'` scope, but to fall-back to the `'queryEngine'` scope if there
|
|
306
|
+
/// is no `'model'` scope to return.
|
|
307
|
+
///
|
|
308
|
+
/// Arguments:
|
|
309
|
+
/// ...scopeNames: Array<string>
|
|
310
|
+
/// Specify the scopes you wish to fetch, in order, from left-to-right. The first
|
|
311
|
+
/// scope found will be returned.
|
|
312
|
+
///
|
|
313
|
+
/// Return: <see>QueryEngine</see> | <see>ModelScope</see> | <see>FieldScope</see>
|
|
314
|
+
/// Return the specified scope, the first found in the list of provided scopes. If
|
|
315
|
+
/// no scope specified is found, then return `this` instead.
|
|
316
|
+
///
|
|
317
|
+
/// See: QueryEngineBase._newQueryEngineScope
|
|
318
|
+
///
|
|
319
|
+
/// See: QueryEngineBase._newModelScope
|
|
320
|
+
///
|
|
321
|
+
/// See: QueryEngineBase._newFieldScope
|
|
88
322
|
_fetchScope(...scopeNames) {
|
|
89
323
|
let context = this.getOperationContext();
|
|
90
324
|
|
|
@@ -110,19 +344,43 @@ class QueryEngineBase extends ProxyClass {
|
|
|
110
344
|
return this;
|
|
111
345
|
}
|
|
112
346
|
|
|
347
|
+
/// Create a new "root scope" (`QueryEngine` scope), push it onto the
|
|
348
|
+
/// "operation stack", and return the newly created scope.
|
|
349
|
+
///
|
|
350
|
+
/// Return: <see>QueryEngine</see>
|
|
351
|
+
/// Return a new "root scope" (`QueryEngine` instance), after pushing
|
|
352
|
+
/// it onto the internal "operation stack". This also "names" the operation
|
|
353
|
+
/// on the stack, so a call to `this._fetchScope('queryEngine')` after this
|
|
354
|
+
/// will return this newly created scope.
|
|
355
|
+
///
|
|
356
|
+
/// See: QueryEngineBase._fetchScope
|
|
113
357
|
_newQueryEngineScope() {
|
|
114
358
|
const QueryEngineClass = this.getQueryEngineClass();
|
|
115
|
-
let context = this.
|
|
359
|
+
let context = this.getOperationContext();
|
|
116
360
|
let newContext = this._inheritContext(context, 'queryEngine');
|
|
117
361
|
let newScope = new QueryEngineClass(newContext);
|
|
118
362
|
|
|
119
363
|
return newScope;
|
|
120
364
|
}
|
|
121
365
|
|
|
366
|
+
/// Create a new "model scope" (`ModelScope` scope), push it onto the
|
|
367
|
+
/// "operation stack", and return the newly created scope.
|
|
368
|
+
///
|
|
369
|
+
/// Arguments:
|
|
370
|
+
/// Model: class <see>Model</see>
|
|
371
|
+
/// The model class for this "model scope".
|
|
372
|
+
///
|
|
373
|
+
/// Return: <see>ModelScope</see>
|
|
374
|
+
/// Return a new "model scope" (`ModelScope` instance), after pushing
|
|
375
|
+
/// it onto the internal "operation stack". This also "names" the operation
|
|
376
|
+
/// on the stack, so a call to `this._fetchScope('model')` after this
|
|
377
|
+
/// will return this newly created scope.
|
|
378
|
+
///
|
|
379
|
+
/// See: QueryEngineBase._fetchScope
|
|
122
380
|
_newModelScope(Model) {
|
|
123
381
|
let ModelScopeClass = this.getModelScopeClass();
|
|
124
382
|
let modelName = Model.getModelName();
|
|
125
|
-
let context = this.
|
|
383
|
+
let context = this.getOperationContext();
|
|
126
384
|
let extra = {};
|
|
127
385
|
let isFirst = !context.rootModel;
|
|
128
386
|
let connection = this.getConnection();
|
|
@@ -162,9 +420,23 @@ class QueryEngineBase extends ProxyClass {
|
|
|
162
420
|
return newScope;
|
|
163
421
|
}
|
|
164
422
|
|
|
423
|
+
/// Create a new "field scope" (`FieldScope` scope), push it onto the
|
|
424
|
+
/// "operation stack", and return the newly created scope.
|
|
425
|
+
///
|
|
426
|
+
/// Arguments:
|
|
427
|
+
/// Field: <see>Field</see>
|
|
428
|
+
/// The field for this "field scope".
|
|
429
|
+
///
|
|
430
|
+
/// Return: <see>FieldScope</see>
|
|
431
|
+
/// Return a new "field scope" (`FieldScope` instance), after pushing
|
|
432
|
+
/// it onto the internal "operation stack". This also "names" the operation
|
|
433
|
+
/// on the stack, so a call to `this._fetchScope('field')` after this
|
|
434
|
+
/// will return this newly created scope.
|
|
435
|
+
///
|
|
436
|
+
/// See: QueryEngineBase._fetchScope
|
|
165
437
|
_newFieldScope(Field) {
|
|
166
438
|
let fieldName = Field.fieldName;
|
|
167
|
-
let context = this.
|
|
439
|
+
let context = this.getOperationContext();
|
|
168
440
|
let FieldScopeClass = this.getFieldScopeClass();
|
|
169
441
|
let extra = {};
|
|
170
442
|
|
|
@@ -186,19 +458,47 @@ class QueryEngineBase extends ProxyClass {
|
|
|
186
458
|
return newScope;
|
|
187
459
|
}
|
|
188
460
|
|
|
189
|
-
|
|
461
|
+
/// Construct a new QueryEngine instance.
|
|
462
|
+
///
|
|
463
|
+
/// Arguments:
|
|
464
|
+
/// context: object
|
|
465
|
+
/// The "root" "operation context" for the query. This is required to contain a
|
|
466
|
+
/// `connection` property, with a valid <see>Connection</see> instance as a value. Besides that, you can apply
|
|
467
|
+
/// any properties you want here, and they will be available on all "operation contexts".
|
|
468
|
+
constructor(_context) {
|
|
190
469
|
super();
|
|
191
470
|
|
|
192
|
-
|
|
471
|
+
let context = Object.create(_context || null);
|
|
472
|
+
|
|
473
|
+
Object.defineProperties(this, {
|
|
474
|
+
'_isMythixQueryEngine': {
|
|
475
|
+
writable: true,
|
|
476
|
+
enumerable: false,
|
|
477
|
+
configurable: true,
|
|
478
|
+
value: true,
|
|
479
|
+
},
|
|
480
|
+
});
|
|
193
481
|
|
|
194
482
|
if (!context)
|
|
195
483
|
throw new TypeError('QueryEngineBase::constructor: "context" required.');
|
|
196
484
|
|
|
197
485
|
if (!context.rootContext) {
|
|
198
|
-
context.
|
|
199
|
-
context.rootContext =
|
|
486
|
+
context._isMythixQueryEngine = true;
|
|
487
|
+
context.rootContext = Object.assign(
|
|
488
|
+
{},
|
|
489
|
+
context,
|
|
490
|
+
{
|
|
491
|
+
contextID: QueryEngineBase.generateID(),
|
|
492
|
+
},
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
context = Object.create(context);
|
|
200
496
|
}
|
|
201
497
|
|
|
498
|
+
context.isQueryOperationContext = true;
|
|
499
|
+
if (!context.contextID)
|
|
500
|
+
context.contextID = QueryEngineBase.generateID();
|
|
501
|
+
|
|
202
502
|
if (!context.operationStack)
|
|
203
503
|
context.operationStack = [];
|
|
204
504
|
|
|
@@ -230,18 +530,99 @@ class QueryEngineBase extends ProxyClass {
|
|
|
230
530
|
});
|
|
231
531
|
}
|
|
232
532
|
|
|
533
|
+
/// Fetch the current (top most) context id of the query.
|
|
534
|
+
///
|
|
535
|
+
/// Each "operation context" gets its own unique ID. This
|
|
536
|
+
/// is primarily for caching and comparison operations.
|
|
537
|
+
/// Since a new context id is generated for each operation
|
|
538
|
+
/// of the query, one can detect if two queries are identical
|
|
539
|
+
/// simply by comparing their ids. This id can also be used for
|
|
540
|
+
/// cache... since the same id always equates to the exact same
|
|
541
|
+
/// query.
|
|
542
|
+
///
|
|
543
|
+
/// Return: number
|
|
544
|
+
/// The unique "operation context" id for this query. This will always
|
|
545
|
+
/// be the id assigned to the top-most "operation context" of the "operation stack".
|
|
233
546
|
getQueryID() {
|
|
234
|
-
return this.
|
|
235
|
-
}
|
|
236
|
-
|
|
547
|
+
return this.getOperationContext().contextID;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/// Return the top-most "operation context" for the query.
|
|
551
|
+
///
|
|
552
|
+
/// The internal operation stack looks like this `[ root context, <- context1, <- context2, <- context3, ... ]`
|
|
553
|
+
///
|
|
554
|
+
/// Operation contexts are simple objects defining the query
|
|
555
|
+
/// operations. Each new context added to the query is pushed
|
|
556
|
+
/// on top the "operation stack" internal to the query. Each
|
|
557
|
+
/// "operation context" also has its `prototype` set to the
|
|
558
|
+
/// previous "frame" in the stack. This means from the top-most
|
|
559
|
+
/// context, you can access attributes from the bottom-most
|
|
560
|
+
/// context--assuming the property you are trying to access
|
|
561
|
+
/// hasn't also be re-set in a higher-level "frame". For example,
|
|
562
|
+
/// you could access a `distinct`, `order`, or `projections`
|
|
563
|
+
/// attribute from the top-most operation context, which will
|
|
564
|
+
/// always be the "most current" value for the operation you
|
|
565
|
+
/// are requesting data for.
|
|
566
|
+
///
|
|
567
|
+
/// Operation contexts always have at least the following properties:
|
|
568
|
+
/// `operator`, `value`, and `queryProp` (used for replaying query operations).
|
|
569
|
+
/// Each context might also have custom properties... for example, a `DISTINCT`
|
|
570
|
+
/// operation will also have a custom `distinct` property it sets that is
|
|
571
|
+
/// the distinct literal itself.
|
|
572
|
+
///
|
|
573
|
+
/// Return: object
|
|
574
|
+
/// The top-most "operation context" on the "operation stack".
|
|
237
575
|
getOperationContext() {
|
|
238
576
|
return this.currentContext;
|
|
239
577
|
}
|
|
240
578
|
|
|
579
|
+
/// Return the entire "operation stack" for the query.
|
|
580
|
+
///
|
|
581
|
+
/// The internal operation stack looks like this `[ root context, <- context1, <- context2, <- context3, ... ]`
|
|
582
|
+
///
|
|
583
|
+
/// Each "frame" on the stack is itself an "operation context". Each
|
|
584
|
+
/// "frame" defines an operation for the query, for example a `MODEL`,
|
|
585
|
+
/// `EQ`, or `DISTINCT` operation. Essentially a Mythix ORM query is
|
|
586
|
+
/// just an array of operations internally--in order. When the query
|
|
587
|
+
/// is being used to interface with the underlying database, the "operation stack"
|
|
588
|
+
/// is walked, and a part generated for each operation in the stack. For example,
|
|
589
|
+
/// a query such as `User.where.id.EQ(1)` would contain the following operations:
|
|
590
|
+
/// `[ { MODEL = User } <- { FIELD = id } <- { operator = EQ, value = 1 } ]`.
|
|
591
|
+
///
|
|
592
|
+
/// Note:
|
|
593
|
+
/// You can dynamically alter the operation stack of a query by using one of
|
|
594
|
+
/// <see>QueryEngineBase.filter</see>, or <see>QueryEngineBase.map</see>. Since
|
|
595
|
+
/// queries are essentially just arrays of operations, they can be treated much
|
|
596
|
+
/// like arrays.
|
|
597
|
+
///
|
|
598
|
+
/// Return: Array<context>
|
|
599
|
+
/// The entire "operation stack" for the query. This **is not** a copy of the stack,
|
|
600
|
+
/// but the entire stack directly... so **do not** mutate this value unless you know
|
|
601
|
+
/// exactly what you are doing.
|
|
241
602
|
getOperationStack() {
|
|
242
|
-
return this.
|
|
243
|
-
}
|
|
244
|
-
|
|
603
|
+
return this.getOperationContext().operationStack;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/// Check if the very last operation in the internal "operation stack"
|
|
607
|
+
/// is a "control" operation. "control" operations are operations that
|
|
608
|
+
/// change how the query behaves, and include `LIMIT`, `OFFSET`, `ORDER`,
|
|
609
|
+
/// `GROUP_BY`, `HAVING`, and `PROJECT`.
|
|
610
|
+
///
|
|
611
|
+
/// Return: boolean
|
|
612
|
+
/// Return `true` if the very last operation on the "operation stack"
|
|
613
|
+
/// is categorized as a `control` level operation.
|
|
614
|
+
///
|
|
615
|
+
/// See: ModelScope.LIMIT
|
|
616
|
+
///
|
|
617
|
+
/// See: ModelScope.OFFSET
|
|
618
|
+
///
|
|
619
|
+
/// See: ModelScope.ORDER
|
|
620
|
+
///
|
|
621
|
+
/// See: ModelScope.GROUP_BY
|
|
622
|
+
///
|
|
623
|
+
/// See: ModelScope.HAVING
|
|
624
|
+
///
|
|
625
|
+
/// See: ModelScope.PROJECT
|
|
245
626
|
isLastOperationControl() {
|
|
246
627
|
let queryParts = this.getOperationStack();
|
|
247
628
|
let lastPart = queryParts[queryParts.length - 1];
|
|
@@ -252,6 +633,13 @@ class QueryEngineBase extends ProxyClass {
|
|
|
252
633
|
return false;
|
|
253
634
|
}
|
|
254
635
|
|
|
636
|
+
/// Check if the very last operation in the internal "operation stack"
|
|
637
|
+
/// is a "condition" operation. "condition" operations are operations that
|
|
638
|
+
/// are conditions for the query, for example `EQ`, `GT`, `LT`, etc...
|
|
639
|
+
///
|
|
640
|
+
/// Return: boolean
|
|
641
|
+
/// Return `true` if the very last operation on the "operation stack"
|
|
642
|
+
/// is categorized as a `condition` level operation.
|
|
255
643
|
isLastOperationCondition() {
|
|
256
644
|
let queryParts = this.getOperationStack();
|
|
257
645
|
let lastPart = queryParts[queryParts.length - 1];
|
|
@@ -262,11 +650,22 @@ class QueryEngineBase extends ProxyClass {
|
|
|
262
650
|
return false;
|
|
263
651
|
}
|
|
264
652
|
|
|
653
|
+
/// Check if the query has any conditions.
|
|
654
|
+
///
|
|
655
|
+
/// A query might not have conditions... if for example
|
|
656
|
+
/// it is defining a table-join.
|
|
657
|
+
///
|
|
658
|
+
/// Return: boolean
|
|
659
|
+
/// Return `true` if the query has any conditions, i.e. `EQ`, or `GT`.
|
|
265
660
|
queryHasConditions() {
|
|
266
661
|
let context = this.getOperationContext();
|
|
267
662
|
return context.hasCondition;
|
|
268
663
|
}
|
|
269
664
|
|
|
665
|
+
/// Check if the query has any table joins.
|
|
666
|
+
///
|
|
667
|
+
/// Return: boolean
|
|
668
|
+
/// Return `true` if the query is joining on tables, or `false` otherwise.
|
|
270
669
|
queryHasJoins() {
|
|
271
670
|
let queryParts = this.getOperationStack();
|
|
272
671
|
for (let i = 0, il = queryParts.length; i < il; i++) {
|
|
@@ -278,6 +677,11 @@ class QueryEngineBase extends ProxyClass {
|
|
|
278
677
|
return false;
|
|
279
678
|
}
|
|
280
679
|
|
|
680
|
+
/// Debug a query.
|
|
681
|
+
///
|
|
682
|
+
/// This will call `console.log` for every operation
|
|
683
|
+
/// on the internal "operation stack", allowing you to
|
|
684
|
+
/// debug each query part--in order.
|
|
281
685
|
logQueryOperations() {
|
|
282
686
|
let query = this.getOperationStack();
|
|
283
687
|
for (let i = 0, il = query.length; i < il; i++) {
|
|
@@ -293,6 +697,20 @@ class QueryEngineBase extends ProxyClass {
|
|
|
293
697
|
}
|
|
294
698
|
}
|
|
295
699
|
|
|
700
|
+
/// Push a new operation onto the internal "operation stack"
|
|
701
|
+
/// for the query.
|
|
702
|
+
///
|
|
703
|
+
/// Arguments:
|
|
704
|
+
/// frame: object
|
|
705
|
+
/// The new "frame" to push onto the stack. This should just be a simple
|
|
706
|
+
/// object containing the correct properties for the operation being added.
|
|
707
|
+
/// This method will then ensure your new object is added as an "operation context",
|
|
708
|
+
/// setting the `prototype` to the previous "operation context" (frame) in
|
|
709
|
+
/// the stack.
|
|
710
|
+
/// context?: object
|
|
711
|
+
/// The context to set as the `prototype` for this new frame. If not provided,
|
|
712
|
+
/// then this will default to the top-most "operation context" already on
|
|
713
|
+
/// top of the internal "operation stack".
|
|
296
714
|
_pushOperationOntoStack(queryPart, _context) {
|
|
297
715
|
let context = _context || this.getOperationContext();
|
|
298
716
|
let operationStack = context.operationStack;
|
|
@@ -306,16 +724,28 @@ class QueryEngineBase extends ProxyClass {
|
|
|
306
724
|
);
|
|
307
725
|
}
|
|
308
726
|
|
|
727
|
+
/// Get the `connection` supplied to the query
|
|
728
|
+
/// engine when it was first created.
|
|
729
|
+
///
|
|
730
|
+
/// Return: <see>Connection</see>
|
|
731
|
+
/// The `connection` that was supplied to the query engine when it was created.
|
|
309
732
|
getConnection() {
|
|
310
|
-
return this.
|
|
733
|
+
return this.getOperationContext().connection;
|
|
311
734
|
}
|
|
312
735
|
|
|
736
|
+
/// Get a model class by name.
|
|
737
|
+
///
|
|
738
|
+
/// This will fetch the `connection` using <see>QueryEngineBase.getConnection</see>,
|
|
739
|
+
/// and then will request the model by name from the connection itself.
|
|
740
|
+
///
|
|
741
|
+
/// Return: class <see>Model</see>
|
|
742
|
+
/// Return the named model class.
|
|
313
743
|
getModel(modelName) {
|
|
314
744
|
let connection = this.getConnection();
|
|
315
745
|
let Model = (connection && connection.getModel(modelName));
|
|
316
746
|
|
|
317
747
|
if (!Model) {
|
|
318
|
-
let models = this.
|
|
748
|
+
let models = this.getOperationContext().models;
|
|
319
749
|
if (models)
|
|
320
750
|
Model = models[modelName];
|
|
321
751
|
}
|
|
@@ -323,18 +753,57 @@ class QueryEngineBase extends ProxyClass {
|
|
|
323
753
|
return Model;
|
|
324
754
|
}
|
|
325
755
|
|
|
756
|
+
/// Fetch the top-most "root scope" or "queryEngine scope".
|
|
757
|
+
///
|
|
758
|
+
/// Return: <see>QueryEngine</see>
|
|
759
|
+
/// The top-most "query engine" scope.
|
|
326
760
|
getQueryEngineScope() {
|
|
327
|
-
return this.
|
|
328
|
-
}
|
|
329
|
-
|
|
761
|
+
return this.getOperationContext().queryEngineScope;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/// Get the `QueryEngine` class that is being used for the query.
|
|
765
|
+
///
|
|
766
|
+
/// This works by calling <see>QueryEngineBase.getQueryEngineScope</see>
|
|
767
|
+
/// and returning the `constructor` property used by this scope. The
|
|
768
|
+
/// `constructor` property will be the `QueryEngine` class itself.
|
|
769
|
+
///
|
|
770
|
+
/// Return: class <see>QueryEngine</see>
|
|
771
|
+
/// The custom `QueryEngine` class being used for the query, or
|
|
772
|
+
/// the `QueryEngine` class Mythix ORM uses (the default).
|
|
330
773
|
getQueryEngineClass() {
|
|
331
|
-
return this.
|
|
774
|
+
return this.getOperationContext().queryEngineScope.constructor;
|
|
332
775
|
}
|
|
333
776
|
|
|
777
|
+
/// Clone this query.
|
|
778
|
+
///
|
|
779
|
+
/// Return: <see>ModelScope</see> | <see>QueryEngine</see>
|
|
780
|
+
/// The query, cloned. By default this will return the
|
|
781
|
+
/// most recent "model scope" from the cloned query... if one is found.
|
|
782
|
+
|
|
334
783
|
clone() {
|
|
335
784
|
return this.map((part) => part)._fetchScope('model');
|
|
336
785
|
}
|
|
337
786
|
|
|
787
|
+
/// Clone this query, filtering the internal "operation stack"
|
|
788
|
+
/// while doing so. This allows the user to entirely alter the
|
|
789
|
+
/// nature of the query. You can filter out any operations you
|
|
790
|
+
/// want to filter out. For example, you could choose to filter
|
|
791
|
+
/// out all `ORDER` operations to ensure a query never has any
|
|
792
|
+
/// order specified.
|
|
793
|
+
///
|
|
794
|
+
/// The signature for the provided `callback` nearly matches the
|
|
795
|
+
/// signature for Javascript's `Array.prototype.filter` method:
|
|
796
|
+
/// `callback(operationContext: object, index: number, operationStack: Array<object>, query: QueryEngine)`
|
|
797
|
+
///
|
|
798
|
+
/// Arguments:
|
|
799
|
+
/// callback: (operationContext: object, index: number, parts: Array<object>, query: QueryEngine) => boolean;
|
|
800
|
+
/// The callback to use for filtering. If this callback returns a "falsy" value, then the operation
|
|
801
|
+
/// will be filtered out.
|
|
802
|
+
///
|
|
803
|
+
/// Return: <see>FieldScope</see> | <see>ModelScope</see> | <see>QueryEngine</see>
|
|
804
|
+
/// Return the last (top-most) scope of the original query... unless it was filtered out.
|
|
805
|
+
/// The returned query will be identical to the original query... minus
|
|
806
|
+
/// any operation that was filtered out.
|
|
338
807
|
filter(callback) {
|
|
339
808
|
const Klass = this.getQueryEngineScopeClass();
|
|
340
809
|
let context = this.getOperationContext();
|
|
@@ -359,6 +828,28 @@ class QueryEngineBase extends ProxyClass {
|
|
|
359
828
|
return query;
|
|
360
829
|
}
|
|
361
830
|
|
|
831
|
+
/// Clone this query, mapping the internal "operation stack"
|
|
832
|
+
/// while doing so. This allows the user to entirely alter the
|
|
833
|
+
/// nature of the query. You can map any operations you
|
|
834
|
+
/// want to alter. For example, you could choose to alter
|
|
835
|
+
/// all `ORDER` operations, forcing a different order for the query.
|
|
836
|
+
///
|
|
837
|
+
/// The signature for the provided `callback` nearly matches the
|
|
838
|
+
/// signature for Javascript's `Array.prototype.map` method:
|
|
839
|
+
/// `callback(operationContext: object, index: number, operationStack: Array<object>, query: QueryEngine)`
|
|
840
|
+
/// The `operationContext` here is a copy of the original operation context, so it has
|
|
841
|
+
/// its `prototype` disconnected from the context chain, and you can feel free to modify it
|
|
842
|
+
/// (without effecting the original query).
|
|
843
|
+
///
|
|
844
|
+
/// Arguments:
|
|
845
|
+
/// callback: (operationContext: object, index: number, parts: Array<object>, query: QueryEngine) => object;
|
|
846
|
+
/// The callback used to map each "operation context". If the return value is "falsy", or a non-object, then
|
|
847
|
+
/// it will be discarded (narrowing the "operation stack" of the final mapped query).
|
|
848
|
+
///
|
|
849
|
+
/// Return: <see>FieldScope</see> | <see>ModelScope</see> | <see>QueryEngine</see>
|
|
850
|
+
/// Return the last (top-most) scope of the original query.
|
|
851
|
+
/// The returned query will be identical to the original query... excepting
|
|
852
|
+
/// any operation that was modified.
|
|
362
853
|
map(callback) {
|
|
363
854
|
const Klass = this.getQueryEngineScopeClass();
|
|
364
855
|
let context = this.getOperationContext();
|
|
@@ -384,6 +875,33 @@ class QueryEngineBase extends ProxyClass {
|
|
|
384
875
|
return query;
|
|
385
876
|
}
|
|
386
877
|
|
|
878
|
+
/// This method recursively walks the query, calling the provided
|
|
879
|
+
/// `callback` for every sub-query encountered. The provided `callback`
|
|
880
|
+
/// will never be called with `this` query (the root query being walked).
|
|
881
|
+
///
|
|
882
|
+
/// The callback signature is `callback(subQuery: QueryEngine, parentOperationContext: object, contextKey: string, depth: number): undefined`
|
|
883
|
+
/// where the `subQuery` is the query found, the `parentOperationContext` is the parent "operation context" that the sub-query was found on,
|
|
884
|
+
/// `contextKey` is the key the sub-query was found on (usually `'value'`) inside the `parentOperationContext`, and `depth` is the
|
|
885
|
+
/// depth at which the sub-query was found, which will always be greater than or equal to `1`
|
|
886
|
+
/// (`0` is reserved for the root query itself).
|
|
887
|
+
///
|
|
888
|
+
/// Note:
|
|
889
|
+
/// Though you wouldn't generally modify the query while walking it
|
|
890
|
+
/// (for that you should instead use <see>Connection.finalizeQuery</see>)
|
|
891
|
+
/// it is possible by setting a new sub-query on the `contextKey` of
|
|
892
|
+
/// the `parentOperationContext`. i.e. `parentOperationContext[contextKey] = newSubQuery`.
|
|
893
|
+
///
|
|
894
|
+
/// Arguments:
|
|
895
|
+
/// callback: (subQuery: QueryEngine, parentOperationContext: object, contextKey: string, depth: number) => void;
|
|
896
|
+
/// The callback that will be called for each sub-query encountered.
|
|
897
|
+
/// contextKeys?: Array<string> = [ 'value' ]
|
|
898
|
+
/// The "operation context" keys to check for sub-queries. This will almost always be "value"
|
|
899
|
+
/// for each operation... however, if you add custom operations that store sub-queries on
|
|
900
|
+
/// other operation context property names, then you would want to supply the names of those
|
|
901
|
+
/// properties here.
|
|
902
|
+
///
|
|
903
|
+
/// Return: undefined
|
|
904
|
+
/// Nothing is returned from this method.
|
|
387
905
|
walk(callback, _checkContextKeys) {
|
|
388
906
|
const walkQueries = (query, parent, contextKey, depth) => {
|
|
389
907
|
let parts = query.getOperationStack();
|
|
@@ -411,7 +929,24 @@ class QueryEngineBase extends ProxyClass {
|
|
|
411
929
|
walkQueries(this, null, null, 0);
|
|
412
930
|
}
|
|
413
931
|
|
|
414
|
-
|
|
932
|
+
/// Fetch all models used in the query.
|
|
933
|
+
///
|
|
934
|
+
/// By default, this will return all unique models
|
|
935
|
+
/// used across the root query, including models used
|
|
936
|
+
/// for table-joining.
|
|
937
|
+
/// You can however pass the `options` `{ subQueries: true }`
|
|
938
|
+
/// to return all models used in the query, including those
|
|
939
|
+
/// used in sub-queries.
|
|
940
|
+
///
|
|
941
|
+
/// Arguments:
|
|
942
|
+
/// options?: object
|
|
943
|
+
/// Options for the operation. The only option supported is `{ subQueries: true }`,
|
|
944
|
+
/// which if enabled, will request that this method also walk sub-queries.
|
|
945
|
+
///
|
|
946
|
+
/// Return: Array<class <see>Model</see>>
|
|
947
|
+
/// An array of all model classes used in the query.
|
|
948
|
+
getAllModelsUsedInQuery(_options) {
|
|
949
|
+
let options = _options || {};
|
|
415
950
|
let Models = new Set();
|
|
416
951
|
let query = this.getOperationStack();
|
|
417
952
|
|
|
@@ -423,10 +958,13 @@ class QueryEngineBase extends ProxyClass {
|
|
|
423
958
|
Models.add(Model);
|
|
424
959
|
} else if (Object.prototype.hasOwnProperty.call(queryPart, 'condition') && queryPart.condition === true) {
|
|
425
960
|
let operatorValue = queryPart.value;
|
|
426
|
-
if (!QueryEngineBase.isQuery(operatorValue)
|
|
961
|
+
if (!QueryEngineBase.isQuery(operatorValue))
|
|
962
|
+
continue;
|
|
963
|
+
|
|
964
|
+
if (options.subQueries !== true && operatorValue.queryHasConditions())
|
|
427
965
|
continue;
|
|
428
966
|
|
|
429
|
-
let SubModels = operatorValue.getAllModelsUsedInQuery();
|
|
967
|
+
let SubModels = operatorValue.getAllModelsUsedInQuery(options);
|
|
430
968
|
for (let j = 0, jl = SubModels.length; j < jl; j++) {
|
|
431
969
|
let Model = SubModels[j];
|
|
432
970
|
Models.add(Model);
|
|
@@ -438,8 +976,30 @@ class QueryEngineBase extends ProxyClass {
|
|
|
438
976
|
return allModels;
|
|
439
977
|
}
|
|
440
978
|
|
|
441
|
-
|
|
442
|
-
|
|
979
|
+
/// Check if the model specified is used in the query.
|
|
980
|
+
///
|
|
981
|
+
/// By default, this will check if the provided `Model`
|
|
982
|
+
/// is used in the root query, or any table-joins in the
|
|
983
|
+
/// root query. You can optionally pass the `options`
|
|
984
|
+
/// `{ subQueries: true }` to also check if the provided
|
|
985
|
+
/// `Model` is used in any sub-queries.
|
|
986
|
+
///
|
|
987
|
+
/// Note:
|
|
988
|
+
/// This internally calls <see>QueryEngineBase.getAllModelsUsedInQuery</see>
|
|
989
|
+
/// an then checks for the existence of the provided `Model` in the result.
|
|
990
|
+
///
|
|
991
|
+
/// Arguments:
|
|
992
|
+
/// Model: class <see>Model</see>
|
|
993
|
+
/// The model class to check for.
|
|
994
|
+
/// options?: object
|
|
995
|
+
/// Options for the operation. The only option supported is `{ subQueries: true }`,
|
|
996
|
+
/// which if enabled, will request that this method also walk sub-queries.
|
|
997
|
+
///
|
|
998
|
+
/// Return: boolean
|
|
999
|
+
/// Return `true` if the specified `Model` is used in the query, or
|
|
1000
|
+
/// any table-joins... `false` otherwise.
|
|
1001
|
+
isModelUsedInQuery(Model, options) {
|
|
1002
|
+
let allModels = this.getAllModelsUsedInQuery(options);
|
|
443
1003
|
return (allModels.indexOf(Model) >= 0);
|
|
444
1004
|
}
|
|
445
1005
|
}
|